App Service plans hosting zero apps while billing reserved compute
What does ZopNight detect here?
An App Service plan with numberOfSites at 0 pays its full tier fee to host nothing. ZopNight reads that count from Resource Graph, then holds fire if the plan's CpuPercentage series shows 5% or more average or peak over a trustworthy 30-day window. Recent activity means apps were just removed, not abandoned.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-222 |
| Category | idle |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | appservice_idle.go |
Where it applies
Empty plans are what app deletion leaves behind
Deleting a web app in Azure does not delete the App Service plan under it. The plan (the
actual billable unit) stays, reserving compute at its full tier rate with a site count of
zero. ZopNight reads the authoritative numberOfSites property that Resource Graph reports for
every server farm; a count of 0 is the primary signal that the tier fee is buying nothing.
Zero sites now, but busy recently: not flagged
A plan can reach zero sites minutes after a migration, mid-reshuffle, with deployment slots or
hybrid connections still winding down. So the rule adds a suppression guard: when a
trustworthy CpuPercentage series exists, meaning at least 30 days of coverage, and its windowed
average or maximum reaches 5% or more, the delete recommendation is withheld. The plan is
empty but warm, and warmth earns it a reprieve until next cycle.
The reverse does not hold: a missing CPU series does not block the finding. An empty plan with no telemetry genuinely has nothing running on it, and the site count stands on its own.
Check a suspect plan in seconds
az appservice plan show -n <plan> -g <rg> \ --query "{sites: numberOfSites, sku: sku.name}" -o jsonaz monitor metrics list \ --resource "$(az appservice plan show -n <plan> -g <rg> --query id -o tsv)" \ --metric CpuPercentage --interval PT1H --offset 30d \ --aggregation Average MaximumTwo exits, one of them free
Deleting the empty plan ends the charge. The often-better move is consolidation: an empty S1 alongside a crowded S1 is an invitation to move apps into one plan and delete the other. Same monthly saving, more headroom where it counts. Either way the saving equals the plan’s full tier fee, which is how ZopNight prices it.
Where the rule stays quiet
Any hosted site, recent CPU activity at or above the 5% floor over a trustworthy window, or an unpriced tier each suppress the finding. Free and shared tiers rarely survive the cost gate, since there is little to reclaim. Reader supplies the site count, Monitoring Reader the CPU series; detection touches nothing else.