Skip to main content
rightsizing · azure

App Service plans that never passed 40% CPU in 30 days and can drop one size

resource types
1
rule IDs covered
1
severity
medium

What does ZopNight detect here?

Azure App Service plans on dedicated tiers bill for every VM instance at the plan's size. ZopNight flags a plan whose `CpuPercentage` peak stayed under 40% for 30 days, with memory averaging under 50%, and prices a one-step move within the same tier, such as `P2V3` to `P1V3`, from real Windows or Linux rates.

Signal and threshold

How ZopNight evaluates App Service plans that never passed 40% CPU in 30 days and can drop one size.
Field Value
Rule IDsRC-1310
Categoryrightsizing
Severitymedium
MetricCpuPercentage
Threshold30-day peak below 40%, memory below 50%
Evaluation window30d
SourceZopNight
Permissions usedMicrosoft.Web/serverfarms/Read · Microsoft.Insights/Metrics/Read

Every instance of an oversized plan is paid for

The plan, not the app, is the billing unit. Microsoft’s hosting plans overview explains that on the dedicated tiers (Basic, Standard and the Premium families) the plan defines how many VM instances the apps run on, and each VM instance is charged. All apps in the plan share those instances and scale together. A plan chosen for a launch and never revisited keeps paying for headroom on every instance.

Reading a plan’s peak CPU and memory

Terminal window
az appservice plan list \
--query "[].{name:name, group:resourceGroup, sku:sku.name, workers:sku.capacity, apps:numberOfSites}" -o table
az monitor metrics list \
--resource /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Web/serverfarms/<plan> \
--metric CpuPercentage MemoryPercentage --aggregation Maximum Average --interval PT1H --offset 30d

What has to be true before a smaller size is suggested

  1. CpuPercentage data covers at least the full 30 days.
  2. The highest CPU reading in that window is below 40%, so even the busiest hour would fit a smaller instance.
  3. If memory data is present, MemoryPercentage averages below 50%, which rules out memory-bound plans.
  4. A smaller size exists in the same tier family. The steps are B3 to B2 to B1, S3 to S2 to S1, and the same within PremiumV2, PremiumV3, PremiumMV3 and IsolatedV2.
  5. Real hourly rates exist for both sizes, using the plan’s operating system, and the plan has a price.

Plans that are not touched

A plan already on the smallest size of its family (B1, S1, P1V2, P0V3 and so on) gets no finding; the rule only moves within a family. Jumping to a cheaper family can remove features such as staging slots or autoscaling, which Microsoft’s scale-up guide ties to the pricing tier. Less than 30 days of CPU data, or any missing rate, also means no finding. A plan with no apps at all is a different case, handled by Idle Azure App Service Plan.

The saving from one size down

Terminal window
saving = (current size hourly rate - smaller size hourly rate) applied to the plan's monthly cost
cost after fix = current cost - saving

The instance count stays the same; only the size of each instance changes.

Scaling the plan down

  1. Review CPU and memory for the whole plan and for each app on it over the last 30 days.
  2. Change the size, in the portal under Scale up, or with az appservice plan update --resource-group <rg> --name <plan> --sku <smaller-size>.
  3. Watch response times and CPU for a few days after the change, and scale back up if the peak crosses your comfort line.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

472 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

472 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·