Azure waste

Provisioned throughput on non-production workloads

Reserved AI capacity on a test workload
The agent reports this
Reversible
Why it happens

Reserving capacity pays off at steady high volume. Test traffic is neither, so paying per request is usually cheaper.

Provisioned throughput is worth it at steady high volume. Development traffic is bursty and low, which is exactly the shape pay-as-you-go is cheaper for.

Paste this into Resource Graph Explorer in the Azure portal.

resources
| where type =~ 'microsoft.cognitiveservices/accounts'
// 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')
| project account = name, resourceGroup, location,
          acctKind = tostring(kind),
          environment = tostring(tags['Environment'])

Resource Graph does not index microsoft.cognitiveservices/accounts/deployments, so the deployments have to come from ARM: az cognitiveservices account deployment list -g <rg> -n <account>. Not filtered to kind OpenAI, because Azure AI Foundry accounts have kind AIServices and host deployments too. The tag column is there to find the non-production accounts first, since a provisioned deployment reserves capacity by the hour while pay-as-you-go charges only for tokens actually sent.

Applies to microsoft.cognitiveservices/accounts/deployments
What the agent does about it

A provisioned OpenAI deployment on an account or resource group tagged non-production, surfaced for review because PTU rarely pays off at that scale.

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.