Azure waste

NAT gateways attached to no subnet

An outbound gateway with nothing routed through it
The agent fixes this
Why it happens

It bills by the hour just for existing. Once the last network is detached it is a fixed charge for a component doing nothing.

A NAT gateway bills a flat hourly rate for existing. Detach the last subnet and the meter keeps running for a component doing nothing.

Paste this into Resource Graph Explorer in the Azure portal.

resources
| where type =~ 'microsoft.network/natgateways'
// 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 subnets = array_length(coalesce(properties.subnets, dynamic([])))
| where subnets == 0
| project name, resourceGroup, location, subnets

Anything returned here is billing its base rate with nothing routing through it.

Applies to microsoft.network/natgateways
What the agent does about it

A NAT gateway associated with no subnet, billing its full hourly rate.

And what stops it

It has to see the same thing on three consecutive runs before it will act, it stays away from anything a person changed recently, and it will not touch a resource unless you tagged it non-production. Untagged counts as production. Every refusal is written down with the rule that caused it.