Introduction
Azure SQL elastic pools share DTU/vCore resources among multiple databases. When one or a few databases consume most resources, other databases in the pool experience performance degradation and throttling.
Symptoms
Pool resource exhausted:
```bash $ az sql elastic-pool show \ --name my-pool \ --server my-server \ --resource-group my-rg \ --query '{DTU:sku.capacity,Used:dtuUsage,DatabaseCount:databaseCount}'
{ "DTU": 400, "Used": 395, # Pool nearly exhausted "DatabaseCount": 15 } ```
Database throttling:
{
"error": {
"code": "ResourceLimitExceeded",
"message": "The elastic pool has reached its DTU limit"
}
}Imbalanced usage:
-- One database using most pool resources
Database A: 350 DTU (87.5% of pool)
Database B: 30 DTU
Database C: 15 DTU
...Common Causes
- 1.No per-database limits - Databases can consume all pool resources
- 2.Mixed workloads - Heavy workload database mixed with light ones
- 3.Insufficient pool capacity - Pool too small for combined workload
- 4.Single heavy database - One database dominates resource usage
- 5.Burstable databases - Databases with occasional high spikes
- 6.Missing monitoring - No visibility into per-database consumption
Step-by-Step Fix
Step 1: Check Pool Resource Usage
```bash # Check pool overall usage az sql elastic-pool show \ --name my-pool \ --server my-server \ --resource-group my-rg \ --query '{Name:name,Sku:sku,DTUUsage:dtuUsage,StorageUsage:storageUsage}'
# Monitor pool metrics az monitor metrics list \ --resource /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/elasticPools/my-pool \ --metric "dtu_usage" \ --query 'value[].timeseries[].data[].average' ```
Step 2: Analyze Per-Database Usage
```sql -- Query per-database resource consumption sqlcmd -S my-server.database.windows.net -d master -U admin -P password -Q " SELECT d.name as database_name, slo.edition, slo.service_objective, slo.elastic_pool_name, ravg.avg_cpu_percent, ravg.avg_data_io_percent, ravg.avg_log_write_percent FROM sys.databases d JOIN sys.database_service_objectives slo ON d.database_id = slo.database_id CROSS APPLY ( SELECT TOP 1 AVG(avg_cpu_percent) as avg_cpu_percent, AVG(avg_data_io_percent) as avg_data_io_percent, AVG(avg_log_write_percent) as avg_log_write_percent FROM sys.dm_db_resource_stats WHERE database_id = d.database_id AND end_time > DATEADD(hour, -24, GETDATE()) ) ravg WHERE slo.elastic_pool_name = 'my-pool' ORDER BY ravg.avg_cpu_percent DESC "
-- Identify databases with high resource usage ```
Step 3: Set Per-Database DTU Limits
```bash # Set max DTU per database az sql db update \ --name heavy-db \ --server my-server \ --resource-group my-rg \ --elastic-pool my-pool \ --max-capacity 50 # Limit to 50 DTU max
# Set min DTU to guarantee resources az sql db update \ --name critical-db \ --server my-server \ --resource-group my-rg \ --elastic-pool my-pool \ --min-capacity 25 # Guaranteed 25 DTU minimum
# Check current per-database limits az sql db show \ --name my-database \ --server my-server \ --resource-group my-rg \ --query '{Min:minCapacity,Max:maxCapacity}' ```
Step 4: Move Heavy Database to Single Database
```bash # If one database dominates pool, move it out az sql db update \ --name heavy-db \ --server my-server \ --resource-group my-rg \ --elastic-pool "" # Remove from pool
# Assign dedicated SKU az sql db update \ --name heavy-db \ --server my-server \ --resource-group my-rg \ --sku Standard \ --capacity 200
# Or create new dedicated pool for heavy databases az sql elastic-pool create \ --name heavy-pool \ --server my-server \ --resource-group my-rg \ --sku Premium \ --capacity 500
az sql db update \ --name heavy-db \ --server my-server \ --resource-group my-rg \ --elastic-pool heavy-pool ```
Step 5: Scale Pool Capacity
```bash # Increase pool DTU if multiple databases need more resources az sql elastic-pool update \ --name my-pool \ --server my-server \ --resource-group my-rg \ --capacity 800 # Increase from 400 to 800 DTU
# For vCore pools az sql elastic-pool update \ --name my-pool \ --server my-server \ --resource-group my-rg \ --capacity 8 \ --family Gen5
# Check available capacities az sql elastic-pool list-editions \ --location eastus \ --query "[?name=='Standard'].{Name:name,Capacities:capacity}" ```
Step 6: Split Databases into Multiple Pools
```bash # Create separate pools by workload type
# Production pool az sql elastic-pool create \ --name prod-pool \ --server my-server \ --resource-group my-rg \ --sku Standard \ --capacity 400
# Dev/test pool az sql elastic-pool create \ --name dev-pool \ --server my-server \ --resource-group my-rg \ --sku Standard \ --capacity 100
# Move databases to appropriate pool az sql db update \ --name prod-db-1 \ --server my-server \ --resource-group my-rg \ --elastic-pool prod-pool
az sql db update \ --name dev-db-1 \ --server my-server \ --resource-group my-rg \ --elastic-pool dev-pool ```
Step 7: Monitor Pool Balance
```bash # Query pool balance metrics az monitor metrics list \ --resource /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/elasticPools/my-pool \ --metric "dtu_usage,database_storage_used" \ --query 'value[].{Name:name.localizedValue,Values:timeseries[].data[]}'
# Create alert for pool exhaustion az monitor metrics alert create \ --name pool-dtu-alert \ --resource-group my-rg \ --scopes /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/elasticPools/my-pool \ --condition "avg dtu_usage > 90" \ --window-size 5m ```
Step 8: Implement Database-Level Monitoring
```sql -- Track per-database usage over time sqlcmd -S my-server.database.windows.net -d master -U admin -P password -Q " -- Create table for historical tracking CREATE TABLE dbo.PoolUsageHistory ( LogTime datetime DEFAULT GETDATE(), DatabaseName nvarchar(128), AvgCpuPercent decimal(5,2), AvgIoPercent decimal(5,2), AvgLogPercent decimal(5,2) )
-- Populate with current stats INSERT INTO dbo.PoolUsageHistory (DatabaseName, AvgCpuPercent, AvgIoPercent, AvgLogPercent) SELECT d.name, AVG(r.avg_cpu_percent), AVG(r.avg_data_io_percent), AVG(r.avg_log_write_percent) FROM sys.databases d CROSS APPLY sys.dm_db_resource_stats r WHERE d.database_id > 4 -- Exclude system databases GROUP BY d.name " ```
Step 9: Optimize Heavy Queries
```sql -- In heavy databases, find expensive queries sqlcmd -S my-server.database.windows.net -d heavy-db -U admin -P password -Q " SELECT TOP 10 qs.query_hash, qs.execution_count, qs.total_worker_time / qs.execution_count as avg_cpu, qs.total_elapsed_time / qs.execution_count as avg_duration, 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 "
-- Optimize identified queries to reduce database load ```
Step 10: Configure Pool Auto-Scaling
```bash # For vCore pools, enable auto-scaling (serverless) az sql elastic-pool update \ --name my-pool \ --server my-server \ --resource-group my-rg \ --capacity 2 # Min vCores
# Set auto-pause for dev/test databases az sql db update \ --name dev-db \ --server my-server \ --resource-group my-rg \ --elastic-pool my-pool \ --auto-pause-delay 60 # Pause after 60 minutes inactivity ```
Elastic Pool Sizing Guide
| Scenario | Recommended Pool | Per-DB Limits |
|---|---|---|
| 10+ light databases | Standard 100-200 DTU | Max 25 DTU each |
| Mixed workloads | Standard 400-800 DTU | Set max per DB |
| One heavy database | Move to single DB | N/A |
| Production + Dev | Separate pools | Different limits |
Verification
```bash # After adjusting pool configuration az sql elastic-pool show \ --name my-pool \ --server my-server \ --resource-group my-rg \ --query '{Name:name,DTU:sku.capacity,Databases:databaseCount}'
# Monitor for 24 hours az monitor metrics list \ --resource /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Sql/servers/my-server/elasticPools/my-pool \ --metric "dtu_usage" \ --start-time "2024-01-15T00:00:00Z" \ --end-time "2024-01-15T23:59:59Z" \ --interval PT1H
# Should show: # - Average DTU usage < 70% # - No individual database exceeding max DTU # - No throttling errors in applications ```
Prevention
To prevent Azure SQL elastic pool imbalance issues from recurring, implement these proactive measures:
1. Monitor Pool DTU Usage
groups:
- name: azure-sql-pool
rules:
- alert: AzureSQLElasticPoolImbalanced
expr: |
azure_sql_elastic_pool_dtu_usage_percent > 90
for: 10m
labels:
severity: warning
annotations:
summary: "Azure SQL elastic pool DTU usage exceeds 90%"2. Implement Database Tiering
```bash # Group databases by resource usage az sql db create --name light-app-db --resource-group my-rg --server my-server --elastic-pool my-light-pool --service-objective elasticPool az sql db create --name heavy-app-db --resource-group my-rg --server my-server --elastic-pool my-heavy-pool --service-objective elasticPool
# Create separate pools based on workload type az sql elastic-pool create --name my-light-pool --resource-group my-rg --server my-server --edition Standard --dtu 50 az sql elastic-pool create --name my-heavy-pool --resource-group my-rg --server my-server --edition Standard --dtu 200 ```
3. Configure Database Limits
```bash # Set min/max DTU per database az sql db update --name my-db --resource-group my-rg --server my-server --elastic-pool my-pool --min-capacity 5 --max-capacity 50
# Prevent single database from consuming all pool resources ```
Best Practices Checklist
- [ ] Monitor pool DTU usage
- [ ] Implement database tiering
- [ ] Configure database min/max limits
- [ ] Review database workload patterns
- [ ] Scale pool before peak usage
- [ ] Monitor individual database usage
Related Issues
- [Fix Azure SQL Database DTU Limit](/articles/fix-azure-sql-database-dtu-limit)
- [Fix Azure SQL Database Geo-Replica Lag](/articles/fix-azure-sql-database-geo-replica-lag)
- [Fix Azure SQL Database Deadlock](/articles/fix-azure-sql-database-deadlock)
Related Articles
- [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 Elastic Pool Imbalanced", "description": "Troubleshoot Azure SQL elastic pool resource imbalance. Adjust per-database limits, move databases, or scale the pool.", "url": "https://www.fixwikihub.com/fix-azure-sql-elastic-pool-imbalanced", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-03T18:22:07.470Z", "dateModified": "2026-04-03T18:22:07.470Z" } </script>