Azure waste

Premium App Configuration store on a non-production store

An App Configuration store on the Premium tier while tagged non-production.
The agent reports this
Reversible
Why it happens

An App Configuration store bills a flat daily rate for its tier regardless of what it holds or how often anything reads it: nothing on Free, about 3.65 US dollars a month on Developer, about 36.50 on Standard and about 292 on Premium. Premium buys a higher request allowance, larger key-value and snapshot storage, and geo-replication with replicas, none of which a development or test store exercises, so the tier is a fixed charge for headroom it will never use. The saving quoted is the move to Standard and never to Free or Developer, because Microsoft supports downgrading only between Premium and Standard, which are both production tiers, and says plainly that downgrading to a non-production tier such as Free is not supported: reaching Free means creating a new store and importing the data, which is a migration rather than a setting, and quoting it as a saving would be quoting a number nobody can act on. Microsoft names one precondition for the supported move, which travels on every finding rather than being assumed away: regular storage and snapshot storage must already be below the Standard limits, verifiable through the Daily Storage Usage and Snapshot Storage Size metrics on the store. The agent does not read those metrics, so a finding states that the precondition is unchecked rather than implying the change is unconditional.

Paste this into Resource Graph Explorer in the Azure portal.

resources
| where type =~ 'microsoft.appconfiguration/configurationstores'
// 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')
| extend tier = tostring(coalesce(sku.name, properties.sku.name))
| where tier =~ 'Premium'
| project name, resourceGroup, location, tier, targetTier = 'Standard', environment = cfopEnv

Reads sku.name, which is where Microsoft's own ARM template reference puts the tier (sku: { name: 'standard' }). properties.sku.name is coalesced in as well because a store returned by an older API version can carry it there, and a store that looked untiered would be skipped silently, which is a miss that looks exactly like a clean estate. The target is Standard and deliberately NOT Free or Developer, even though both are cheaper: Microsoft supports downgrading only between Premium and Standard, both production tiers, and states that downgrading to a non-production tier such as Free is not supported. Reaching Free or Developer means creating a new store and importing the data, so quoting either as a saving would quote a number nobody can act on. One precondition this query cannot check, and neither can the agent: Microsoft requires regular storage and snapshot storage to be below the Standard limits before the downgrade, verifiable through the Daily Storage Usage and Snapshot Storage Size metrics on the store. Confirm those before changing the tier.

Applies to microsoft.appconfiguration/configurationstores
What the agent does about it

An App Configuration store on the Premium tier while tagged non-production.

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.