Introduction

Azure SQL Database uses Database Transaction Units (DTUs) to measure resource consumption (CPU, memory, I/O). When DTU usage exceeds the tier limit, queries are throttled, connections may fail, and performance degrades significantly.

Symptoms

DTU throttling error:

sql
Error: 10936, Resource governor limit reached
The resource limit for the database has been reached. Please try again later.

Connection refused:

json
{
  "error": {
    "code": "ResourceLimitExceeded",
    "message": "The request limit for the database is exceeded. Maximum concurrent requests: 100."
  }
}

Slow query performance:

```bash $ az sql db show \ --name my-database \ --server my-server \ --resource-group my-rg \ --query '{ServiceTier:sku.name,DTUCapacity:sku.capacity}'

# Query returns tier limits, but monitoring shows exceeding ```

Common Causes

  1. 1.Tier too low - Basic/Standard tier insufficient for workload
  2. 2.Query inefficiency - Poorly optimized queries consume excessive DTUs
  3. 3.High concurrency - Too many simultaneous connections/queries
  4. 4.Batch operations - Large data imports/exports spike DTU usage
  5. 5.Missing indexes - Full table scans consume high CPU and I/O
  6. 6.Connection leaks - Open connections not properly closed
  7. 7.Scheduled jobs - Concurrent scheduled tasks exceed limits

Step-by-Step Fix

Step 1: Check DTU Usage

```bash # Check current DTU usage az monitor metrics list \ --resource /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/databases/my-database \ --metric "dtu_usage" \ --query 'value[].timeseries[].data[].average'

# Check DTU limit az sql db show \ --name my-database \ --server my-server \ --resource-group my-rg \ --query '{Name:name,Sku:sku,MaxDTU:sku.capacity}' ```

Step 2: Analyze Resource Consumption

```sql -- Query DTU breakdown via sys.dm_db_resource_stats sqlcmd -S my-server.database.windows.net -d my-database -U admin -P password -Q " SELECT AVG(avg_cpu_percent) as avg_cpu, AVG(avg_data_io_percent) as avg_io, AVG(avg_log_write_percent) as avg_log, AVG(avg_memory_usage_percent) as avg_memory, MAX(avg_cpu_percent) as max_cpu, MAX(avg_data_io_percent) as max_io FROM sys.dm_db_resource_stats WHERE end_time > DATEADD(hour, -1, GETDATE()) "

-- If avg_cpu > 80%, CPU is bottleneck -- If avg_io > 80%, I/O is bottleneck ```

Step 3: Upgrade Service Tier

```bash # Check available tiers az sql db list-editions \ --location eastus \ --query "[?contains(name, 'Standard') || contains(name, 'Premium')].{Name:name,Capacity:capacity,Unit:unit}"

# Upgrade to higher tier az sql db update \ --name my-database \ --server my-server \ --resource-group my-rg \ --sku Standard \ --capacity 200 # S3 tier (200 DTU)

# Or upgrade to Premium for vCore model az sql db update \ --name my-database \ --server my-server \ --resource-group my-rg \ --sku Premium \ --capacity 4 \ --family Gen5

# Or use elastic pool for shared DTU az sql elastic-pool create \ --name my-pool \ --server my-server \ --resource-group my-rg \ --sku Standard \ --capacity 400 # Shared among multiple databases ```

Step 4: Identify High DTU Queries

```sql -- Find queries consuming high CPU sqlcmd -S my-server.database.windows.net -d my-database -U admin -P password -Q " SELECT TOP 10 qs.query_hash, qs.execution_count, qs.total_elapsed_time / qs.execution_count as avg_elapsed_time_ms, qs.total_worker_time / qs.execution_count as avg_cpu_time_ms, qs.total_logical_reads / qs.execution_count as avg_reads, SUBSTRING(st.text, (qs.statement_start_offset/2)+1, ((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) as query_text FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st ORDER BY qs.total_worker_time DESC "

-- Queries with high avg_cpu_time_ms are DTU-heavy ```

Step 5: Optimize High DTU Queries

```sql -- Check execution plans for expensive queries sqlcmd -S my-server.database.windows.net -d my-database -U admin -P password -Q " SELECT qp.query_plan, st.text FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp WHERE qs.total_worker_time > 10000000 "

-- Common optimizations: -- 1. Add missing indexes CREATE INDEX IX_Orders_CustomerId ON Orders(CustomerId);

-- 2. Reduce query scope SELECT TOP 100 * FROM LargeTable WHERE Date > '2024-01-01';

-- 3. Use query hints SELECT * FROM Orders WITH (NOLOCK) WHERE CustomerId = 1;

-- 4. Batch operations instead of single-row INSERT INTO Target (Col1, Col2) SELECT Col1, Col2 FROM Source WHERE Processed = 0; ```

Step 6: Check for Missing Indexes

```sql -- Query missing index recommendations sqlcmd -S my-server.database.windows.net -d my-database -U admin -P password -Q " SELECT mid.statement as table_name, mid.equality_columns, mid.inequality_columns, mid.included_columns, migs.avg_user_impact, migs.user_seeks, migs.user_scans FROM sys.dm_db_missing_index_details mid JOIN sys.dm_db_missing_index_groups mig ON mid.index_handle = mig.index_handle JOIN sys.dm_db_missing_index_group_stats migs ON mig.index_group_handle = migs.group_handle ORDER BY migs.avg_user_impact DESC "

-- Create high-impact missing indexes CREATE INDEX IX_Missing_Index ON TableName(Column1, Column2) INCLUDE (Column3); ```

Step 7: Implement Connection Pooling

```bash # Application connection pooling configuration # .NET example: ConnectionString = "Server=my-server.database.windows.net;Database=my-database;User Id=admin;Password=***;Pooling=true;Min Pool Size=5;Max Pool Size=100;Connection Timeout=30;"

# Java example: ConnectionPoolDataSource ds = new ConnectionPoolDataSource(); ds.setUrl("jdbc:sqlserver://my-server.database.windows.net;database=my-database"); ds.setMinPoolSize(5); ds.setMaxPoolSize(100);

# Benefits: # - Reuses connections instead of creating new # - Reduces connection overhead DTU consumption # - Limits concurrent connections ```

Step 8: Schedule Heavy Operations

```bash # Schedule batch operations during low usage # Via Azure Automation or scheduled jobs

# Check usage pattern az monitor metrics list \ --resource /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/databases/my-database \ --metric "dtu_usage" \ --start-time "2024-01-15T00:00:00Z" \ --end-time "2024-01-15T23:59:59Z" \ --interval PT1H

# Schedule heavy queries during off-peak hours (e.g., 2-6 AM) ```

Step 9: Use Elastic Pool

```bash # For multiple databases with variable usage az sql elastic-pool show \ --name my-pool \ --server my-server \ --resource-group my-rg \ --query '{Name:name,DTU:sku.capacity,DatabaseCount:databaseCount}'

# Add database to pool az sql db update \ --name my-database \ --server my-server \ --resource-group my-rg \ --elastic-pool my-pool

# Set per-database limits in pool az sql db update \ --name my-database \ --server my-server \ --resource-group my-rg \ --elastic-pool my-pool \ --max-capacity 50 # Max DTU for this database ```

Step 10: Monitor and Alert

```bash # Create alert for DTU threshold az monitor metrics alert create \ --name sql-dtu-alert \ --resource-group my-rg \ --scopes /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/databases/my-database \ --condition "avg dtu_usage > 80" \ --window-size 5m \ --evaluation-frequency 1m

DTU Tier Limits

TierDTU RangeMax StorageBest For
Basic52 GBDevelopment
Standard S0-S310-100250 GBLight workloads
Standard S4-S12200-3000500 GB-4 TBMedium workloads
Premium P1-P15125-4000500 GB-4 TBCritical workloads

Verification

```bash # After upgrading tier or optimizing az sql db show \ --name my-database \ --server my-server \ --resource-group my-rg \ --query '{Sku:sku.name,Capacity:sku.capacity}'

# Monitor DTU usage for 24 hours az monitor metrics list \ --resource /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/databases/my-database \ --metric "dtu_usage" \ --query 'value[].timeseries[].data[].average'

# Should show average < 80% of new capacity ```

Prevention

To prevent Azure SQL DTU limit issues from recurring, implement these proactive measures:

1. Monitor DTU Usage

yaml
groups:
- name: azure-sql-dtu
  rules:
  - alert: AzureSQLDTUHighUsage
    expr: |
      azure_sql_dtu_usage_percent > 85
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "Azure SQL database DTU usage exceeds 85%"

2. Set Up Auto-Scale

```bash # Configure autoscale for Azure SQL az monitor autoscale create \ --resource /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/databases/my-database \ --name sql-autoscale \ --min-capacity 10 \ --max-capacity 100 \ --count 50

# Add scale-out rule az monitor autoscale rule create \ --resource-group my-rg \ --autoscale-name sql-autoscale \ --scale out 10 \ --condition "dtu_usage > 80 count 5m" ```

3. Optimize Queries Regularly

```sql -- Weekly query performance review SELECT TOP 10 query_text, execution_count, total_elapsed_time / execution_count as avg_time FROM sys.dm_exec_query_stats CROSS APPLY sys.dm_exec_sql_text(sql_handle) ORDER BY avg_time DESC;

-- Identify missing indexes SELECT * FROM sys.dm_db_missing_index_details; ```

Best Practices Checklist

  • [ ] Monitor DTU usage with alerts
  • [ ] Set up auto-scale
  • [ ] Optimize queries regularly
  • [ ] Review index usage
  • [ ] Scale before peak usage
  • [ ] Use elastic pools for multiple databases
  • [Fix Azure SQL Database Deadlock](/articles/fix-azure-sql-database-deadlock)
  • [Fix Azure SQL Transaction Log Full](/articles/fix-azure-sql-transaction-log-full)
  • [Fix Azure SQL Query Timeout](/articles/fix-azure-sql-database-dtu-limit)
  • [Technical troubleshooting: Fix Azure Aks Pod Crashloopbackoff Issue in Azure](azure-aks-pod-crashloopbackoff)
  • [Technical troubleshooting: Fix Azure Api Management Policy Expression Runtime](azure-api-management-policy-expression-runtime-error)
  • [Technical troubleshooting: Fix Azure App Configuration Feature Flag Not Refre](azure-app-configuration-feature-flag-not-refreshing)
  • [Technical troubleshooting: Fix Azure App Service 503 Always On Disabled Issue](azure-app-service-503-always-on-disabled)
  • [Technical troubleshooting: Fix Azure Application Gateway Err SSL Unrecognized](azure-application-gateway-err-ssl-unrecognized-name-alert)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix Azure SQL Database DTU Limit", "description": "Troubleshoot Azure SQL DTU throttling. Upgrade service tier, optimize queries, and implement connection pooling.", "url": "https://www.fixwikihub.com/fix-azure-sql-database-dtu-limit", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-03T15:47:12.852Z", "dateModified": "2026-04-03T15:47:12.852Z" } </script>