# Azure App Service Plan Right-sizing

> Peak, not average, decides a safe App Service downsize: ZopNight only flags a plan when its hourly-maximum CPU never reached 40% across 30 full days of coverage and memory stayed under 50%. The saving is the real rate gap to the tier one rung down, on matching Linux or Windows pricing.

Source: https://zop.dev/integrations/azure/recommendations/azure-app-service-plan-right-sizing
Updated: 2026-08-19

---

## Averages lie about web workloads

Web traffic is spiky, and a plan averaging 12% CPU can still hit 90% every lunchtime. Downsize
on the average and those peaks start timing out. This rule gates on the trustworthy hourly
maximum instead: only when the busiest hour in 30 days stayed under 40% CPU does the plan
qualify, because even that busiest hour would fit inside a one-rung-smaller tier's headroom.
Deliberately, there is no zero-traffic test here; a lightly-but-continuously used plan can
still be badly oversized, and the empty-plan case belongs to a separate idle rule.

## Two ways to be wrongly small

Memory guards the decision alongside CPU: when the plan's memory series averages 50% or more,
the finding is suppressed. Memory-bound plans get slower, not cheaper, on fewer cores. And
the CPU series must carry a full 30 days of hourly-maximum coverage before any of it is
believed; freshly monitored plans read artificially low for lack of data.

## Rates matched to your OS, or nothing

App Service pricing differs between Linux and Windows plans, so the rule looks up both the
current tier and the one-rung-smaller target under OS-specific rate keys. The recommendation
ships only when both real rates exist and produce a sane delta: a P2v3 to P1v3 step, priced
from your region's actual rates. Missing rates mean abstain; the rule never falls back to an
estimated percentage of the bill.

## Replay the peak analysis

```bash
az monitor metrics list \
  --resource "$(az appservice plan show -n <plan> -g <rg> --query id -o tsv)" \
  --metric CpuPercentage MemoryPercentage \
  --interval PT1H --offset 30d --aggregation Maximum Average
```

Scan the Maximum column for any hour at 40 or above.

## Downsizing a live plan

A tier change applies to every app on the plan and takes effect within minutes, no restart
required in most cases. Move down one rung, watch response times and the CPU peak for a week,
and repeat if the new peak still clears the bar comfortably.

## Detection inputs

Reader for plan properties, Monitoring Reader for CPU and memory series, Cost Management
Reader for the billed baseline the delta applies to.
