Azure SQL databases under 5% DTU with no successful connections in 30 days
What does ZopNight detect here?
Azure SQL Database keeps charging for provisioned compute even when no application connects. ZopNight flags a database when DTU consumption averages under 5% and `connection_successful` records zero logins over 30 days, then prices either an auto-pause change for serverless databases or a one-tier step down for provisioned ones.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-203 |
| Category | idle |
| Severity | medium |
| Metric | DTU percentage |
| Threshold | average below 5% and zero successful connections |
| Evaluation window | 30d |
| Source | ZopNight |
| Permissions used | Microsoft.Sql/servers/databases/read · Microsoft.Insights/Metrics/Read |
Where it applies
A database nobody logs into still bills its compute
A provisioned Azure SQL database, whether in the DTU model or on a fixed vCore count, is billed for the compute it reserves, not the queries it serves. The serverless tier is the exception: Microsoft’s serverless overview explains that it pauses databases during inactive periods, when only storage is billed, and that the auto-pause delay can be set as low as 15 minutes. Auto-pause is only supported in the General Purpose service tier.
A database left behind by a finished project, or by an app that moved to a new server, keeps its full compute bill. That is the case this rule is looking for.
Reading DTU and connection metrics yourself
List the databases on a server with their SKU, then check a month of load and logins for any that look quiet:
az sql db list --resource-group <rg> --server <server> \ --query "[].{name:name, sku:sku.name, tier:sku.tier}" -o table
az monitor metrics list \ --resource /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Sql/servers/<server>/databases/<db> \ --metric dtu_consumption_percent connection_successful \ --aggregation Average Total --interval PT1H --offset 30dTwo signals must agree before a database is flagged
- Average DTU consumption over the last 30 days is below 5%.
- The successful-connection count is present and is zero for the window. This metric is required: if it is missing there is no finding, and a single successful login means the database is in use.
- The database has a positive monthly price.
When the rule stays quiet
A database attached to a known active schedule is left alone, since it is parked on purpose rather than abandoned. A serverless database with no measured idle fraction gets no finding, because there is no honest number to put on it. A provisioned database with no smaller DTU tier to move to, or with a missing tier price, is also skipped: the rule never falls back to a guessed percentage.
For databases that do have users but are oversized, see Azure SQL Right-sizing.
How each branch is priced
serverless: saving = monthly cost x measured idle fraction (compute pauses, storage keeps billing)provisioned: saving = current tier rate - next smaller DTU tier rate, per monthBoth figures come from real rates. Neither branch assumes the database is deleted, so the saving is deliberately smaller than the full bill.
Acting on an idle SQL database
- Confirm in Azure Monitor that CPU or DTU load and successful connections really are flat, and that no linked service or job still points at the database.
- Serverless: set an auto-pause delay, for example
az sql db update --resource-group <rg> --server <server> --name <db> --auto-pause-delay 60. Storage continues to bill while paused. - Provisioned: move down one DTU tier with
az sql db update ... --service-objective <smaller-tier>. - If nothing needs the data, export it and delete the database.