Underutilised App Service plans
A web hosting plan on a pricier tier than it needs
Why it happens
The top tiers buy features like private networking. If the site is not using them, a cheaper tier does the same job.
A Premium plan gets chosen for a feature nobody ended up using, and the workload would sit comfortably on Standard.
Paste this into Resource Graph Explorer in the Azure portal.
resources
| where type =~ 'microsoft.web/serverfarms'
// Scope below matches CloudFinOpsPro policy DEFAULTS: exclusions.protectTag, environment.tagKeys,
// environment.allowedTagValues, and allowUntagged false so an untagged resource counts as production.
// If your policy.yaml differs, edit the three lines below or this will disagree with your own agent.
| where tolower(tostring(coalesce(tags['cfop:protect'], ''))) !in ('true', 'yes', '1')
| extend cfopEnv = tolower(trim(' ', tostring(coalesce(tags['Environment'], tags['environment'], tags['env'], ''))))
| where cfopEnv in ('dev', 'development', 'test', 'qa', 'sandbox', 'nonprod', 'non-prod', 'staging')
| where sku.tier has 'Premium'
// The check moves a plan to a cheaper TIER, so it needs a plan that is actually running
// something: an empty plan is empty_app_service_plan's territory and its remedy is
// deletion, not a downgrade. The join then keeps only SKUs with a cross-tier target.
| where properties.numberOfSites > 0
| extend sku = tostring(sku.name)
| join kind=inner (
datatable(sku: string, proposedSku: string) [
'P0v3', 'S1',
'P0v4', 'S1',
'P1', 'S1',
'P1v2', 'S1',
'P1v3', 'S2',
'P1v4', 'S2',
'P2', 'S2',
'P2v2', 'S2',
'P2v3', 'S3',
'P2v4', 'S3',
'P3', 'S3',
'P3v2', 'S3',
'P3v3', 'S3',
'P3v4', 'S3'
]
) on sku
| project name, resourceGroup, location, sku, proposedSku,
sites = toint(properties.numberOfSites)
| order by sku asc, name ascEach row is a plan and the Standard SKU the agent would move it to. Empty plans are excluded because the remedy for one is deletion rather than a downgrade, which is empty_app_service_plan's check. Premium v4 is here now: it publishes specs identical to Premium v3 SKU for SKU, so it maps the same way. The memory-optimised SKUs (P1mv3 and siblings) are deliberately absent rather than pending. A P1mv3 is 2 vCPU / 16 GB and the nearest Standard SKU is 3.5 GB; such a plan exists because the workload needs memory per core, so moving it to Standard removes the reason the plan was chosen. Being listed here is also not enough on its own: the agent additionally requires the move to be CHEAPER in your own region, and on Linux it often is not. A Linux P1v3 is $113.15 a month in East US and an S2 is $138.70, so the agent refuses that one rather than reporting it as a $0 saving. Resource Graph holds no metrics, so this cannot apply the part that decides: the check additionally requires CpuPercentage below its threshold, and it checks that the workload FITS the Standard tier. Every target has less memory than the source and the cut is not uniform - P1v3's 8 GB to an S2's 3.5 GB is 2.29x, P3v3's 32 GB to an S3's 7 GB is 4.57x - so the memory peak is projected onto the target and the plan is dropped if it would exceed 80%. Premium v1 publishes no RAM figure, so for those the fit is reported as unchecked rather than assumed. Resource Graph holds no metrics, so this cannot apply the part that decides: the check additionally requires CpuPercentage below its threshold, averaged over the window. Note the metric is CpuPercentage on Microsoft.Web/serverfarms, not the Percentage CPU that virtual machines publish. Check whether anything on the plan needs a Premium-only feature such as VNet integration before moving.
Applies to microsoft.web/serverfarmsWhat the agent does about it
A plan whose observed load fits a cheaper tier, not just a smaller SKU inside the current tier.
It will not fix this one
It reports this and takes no action. A check only earns the right to change something once the action behind it can re-read live state before it fires and knows the way back.
Related checks
App Service plan with no apps
A paid App Service plan hosting no applications.
App Service plan larger than its sustained demand
A plan whose sustained CPU and memory sit far below the tier it is provisioned in.
Functions Premium plan with negligible executions
An Elastic Premium plan whose function apps execute rarely enough that Consumption would cost far less.