The Stopped vs. Deallocated State Trap
One of the most frequent sources of unexpected Azure billing is the subtle difference between shutting down an instance from the operating system versus deallocating it via the Azure control plane.
When an engineer executes `shutdown -h now` on Linux or clicks 'Shut Down' in Windows Server, the OS powers off, but Azure marks the VM status as PowerState/stopped. Because CPU cores and physical memory slots remain dedicated on the Azure hypervisor, compute charges continue to accrue at 100% of the provisioned rate.
Only virtual machines in 'PowerState/deallocated' stop billing compute cores. OS and data disk storage fees continue until the attached disks are deleted.
Querying Azure Resource Graph for Stopped Instances
To locate all virtual machines across your tenant that are currently stopped but still incurring compute billing, you can execute a Kusto query via the Azure Resource Graph Explorer:
Resources
| where type =~ 'microsoft.compute/virtualmachines'
| extend powerState = tostring(properties.extended.instanceView.powerState.code)
| where powerState =~ 'PowerState/stopped'
| project name, resourceGroup, subscriptionId, location, properties.hardwareProfile.vmSizeDetecting Low-Utilization VMs (<5% CPU)
Beyond completely stopped instances, oversized development and staging VMs often run 24/7 with near-zero activity. WasteRadar analyzes 14-day telemetry curves from Azure Monitor to identify instances averaging under 5% CPU utilization.
For these workloads, engineers can either downscale the instance to a burstable B-series SKU (such as Standard_B2s or Standard_B2ms) or schedule automated deallocation during off-peak hours.
Automated & CLI Remediation Commands
To properly deallocate a stopped virtual machine and release its compute reservation, execute the following Azure CLI command:
# Deallocate a single stopped VM
az vm deallocate --resource-group rg-workloads --name vm-batch-worker
# Check the confirmed power state
az vm get-instance-view --resource-group rg-workloads --name vm-batch-worker --query "instanceView.statuses[?starts_with(code, 'PowerState/')].code" -o tsvPreventing Compute Waste with WasteRadar
Manual CLI queries require ongoing developer effort. Odinext WasteRadar runs automated daily discovery scans across all subscriptions, calculating the exact dollar impact using live Azure Retail Prices meters and dispatching proactive alerts to Slack and email before monthly invoices close.
Odinext Cloud Engineering
Azure Infrastructure & FinOps Research
The Odinext engineering team specializes in Azure cost management, ARM resource optimization, and automated cloud waste detection across enterprise multi-subscription architectures.
Automate This Analysis with WasteRadar
Stop running manual resource queries and spreadsheets. Odinext WasteRadar detects idle compute, unattached disks, and orphaned snapshots automatically with 100% read-only Azure IAM integration.