App Service plans with zero apps that still bill for their VM instances
What does ZopNight detect here?
ZopNight flags an Azure App Service plan whose `numberOfSites` is 0, meaning no web app, API or function app is assigned to it, unless `CpuPercentage` reached 5% in the last 30 days. Microsoft states that a plan with all its apps deleted keeps accruing charges for its tier and instance count, so the empty plan is the whole saving.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-222 |
| Category | idle |
| Severity | medium |
| Metric | CpuPercentage (activity guard) |
| Threshold | numberOfSites = 0, CPU below 5% |
| Evaluation window | 30d |
| Source | ZopNight |
| Permissions used | Microsoft.Web/serverfarms/Read · Microsoft.Insights/Metrics/Read |
Where it applies
An App Service plan bills for instances, not for apps
In App Service, the plan is the compute. On the Basic, Standard and Premium tiers, Microsoft’s hosting plan overview says the plan defines the number of VM instances and each instance is charged; only the Free tier carries no charge. The apps on it do not add to that price.
Take the apps away and nothing changes. The cost planning guide says it plainly: when you delete all apps in a plan, the plan continues to accrue charges based on its pricing tier and number of instances, and you should delete it or scale it down to Free.
Listing empty plans
az appservice plan list \ --query "[?numberOfSites==\`0\`].{name:name, rg:resourceGroup, sku:sku.name, workers:sku.capacity}" \ -o tablenumberOfSites is the number of apps assigned to the plan, as reported by the App Service API.
What ZopNight checks before flagging an empty plan
- The plan’s app count, read from Azure Resource Graph, is exactly 0.
- The plan shows no recent activity: when at least 30 days of
CpuPercentagedata exist, both the average and the peak must be below 5%. CPU at or above that level suggests something is still running on the instances, so ZopNight holds off. - The plan has a known monthly cost above zero.
Plans that are not reported
If the app count could not be read, there is no finding; an unknown is not treated as zero. Plans with any app assigned are out of scope here. A plan that hosts apps but is larger than they need is a sizing question, handled by Azure App Service Plan Right-Sizing. Free-tier plans have no cost to recover and do not appear.
Saving is the plan’s fixed monthly fee
saving = current monthly cost of the plan (tier rate x instance count)cost after fix = 0Removing or reusing an empty plan
- Confirm no deployment pipeline expects to create apps on this plan by name.
- If apps elsewhere could use it, move them onto this plan and delete their old, emptier plans instead; that keeps one plan billing rather than two.
- Otherwise delete it:
az appservice plan delete --resource-group my-rg --name my-plan --yes. - If you want to keep the plan for later, scale it to Free with
az appservice plan update --resource-group my-rg --name my-plan --sku FREE, where the tier and operating system allow it.