Stopped is not deallocated: the basics
Why a virtual machine you switched off can still be on your bill
An Azure virtual machine has two different ways to be off, and only one of them stops the compute charge. When you shut a VM down from inside the guest operating system, with a Windows 'shutdown /s' or a Linux 'sudo shutdown now', the machine powers off but Azure keeps the underlying host reserved for it. Azure calls this the Stopped state, and because the CPU, memory and host capacity stay allocated to you, the per-second compute meter keeps running. The VM looks switched off in every practical sense, and the bill does not change.
The other way is to deallocate. When you stop a VM through the Azure portal, the CLI or PowerShell, Azure releases the host back to the pool. This is the Stopped (deallocated) state, and it is the only one that stops compute billing. You still pay for the managed disks attached to the VM, for any static public IP, and for any reserved capacity, but the compute charge, which is the large part for most VM sizes, goes to zero. The gap between Stopped and Stopped (deallocated) is the entire saving this lesson is about.
Almost nobody leaves a VM in the Stopped state on purpose. It is drift: an admin RDP'd in and hit shut down, a maintenance script ran an in-guest reboot that hung, an automation flow stopped the OS instead of calling deallocate. The machine then sits there, off and useless, quietly billing for compute, sometimes for months. The Azure Cost Optimization workbook surfaces exactly these on its Usage Optimization tab, in the Compute section, under the 'Virtual Machines in a Stopped State' query, and Azure Advisor raises the same machines as a cost recommendation.
In this lesson you will learn the difference between an Azure VM that is stopped and one that is deallocated, why only the second stops the compute charge, how to find every improperly stopped machine across a subscription, and how to deallocate them safely and stop the problem coming back. The fix is reversible and carries no performance trade-off, because the machines in scope are already switched off.
The machine that was off for a year and still got paid for
The Stopped-versus-deallocated trap catches almost everyone the first time, because every instinct from running physical servers says that a powered-off box costs nothing. In Azure it does not work that way: shut a VM down from inside the guest OS and Azure keeps the host reserved, so the compute meter never pauses. People discover this when a VM they switched off 'to save money' months ago turns up on the bill at full rate, having quietly charged the entire time. Microsoft built the warning right into the portal, which now labels the in-guest state 'Stopped' and the released state 'Stopped (deallocated)' precisely so the difference stops being a surprise.
Finding the machines that are off but still billing
Priya runs the platform team at a company doing its first serious Azure cost review. The Cost Optimization workbook's 'Virtual Machines in a Stopped State' query lists nine machines across the dev and test subscriptions that are stopped but not deallocated.
Before deallocating anything, Priya lists the VMs by power state so she can separate the genuinely deallocated machines from the ones that are stopped from inside the guest and still charging for compute.
List every VM with its power state. The '-d' flag asks for instance details, which is what populates powerState. The ones to fix read 'VM stopped', not 'VM deallocated'.
'VM stopped' is the costly state: the machine is off but the host is reserved and compute keeps billing. 'VM deallocated' is the one that has actually stopped charging.
Why stopped keeps billing and deallocated does notdeep dive
An Azure VM's power state comes from the instance view, where a status code of 'PowerState/stopped' or 'PowerState/deallocated' tells you which kind of off it is. The CLI surfaces this as the powerState field on 'az vm list -d', reading 'VM stopped' or 'VM deallocated'. The difference is not cosmetic: in the Stopped state the host that runs your VM stays reserved for you, so the size's compute capacity is held aside and you keep paying the full per-second compute rate. In the deallocated state that host goes back into the shared pool, so there is nothing to bill for compute.
The state you land in depends entirely on how the machine was switched off. A shutdown issued from inside the guest, an OS 'shutdown', a hung in-guest reboot, an agent that powered the OS down, leaves the VM Stopped and still allocated, because Azure was never told to release the host. A stop issued through the control plane, the portal Stop button, 'az vm deallocate', or 'Stop-AzVM' without the '-StayProvisioned' flag, deallocates it. This is why a machine can be off and on the bill at the same time: the guest is down but the control plane still holds the host.
Deallocating does not touch your data. The OS disk and any data disks are managed disks that exist independently of the VM's running state, so they persist and keep their own (much smaller) charge whether the machine is allocated or not. Starting the VM again reattaches it to a fresh host from the pool. The only things that can change across a deallocate are an ephemeral public IP, which is released, and any reliance on the same physical host, which deallocation deliberately drops. Neither matters for a machine you intend to leave off.
What is the impact of leaving VMs stopped but not deallocated?
The direct impact is money spent for nothing. A VM in the Stopped (not deallocated) state charges full compute rate while delivering zero work, so every hour it sits there is pure waste. Because nobody is using the machine, nothing flags it operationally: there are no failed requests, no alerts, no user complaints, just a line on the bill that nobody connects to a switched-off box. That silence is exactly why the waste accumulates, often across months and across a whole fleet of forgotten dev and test machines.
The second-order impact is that the waste compounds and hides. Each improperly stopped VM is a small, steady leak, and a large estate accumulates many of them as people shut machines down the convenient way. They blend into the compute line where they are hard to spot without specifically querying for power state, so a subscription can carry a meaningful recurring cost for switched-off machines while every individual amount looks too small to chase.
The flip side is what makes this worth doing first: the impact of fixing it is entirely positive with no offsetting cost. Deallocating stops the compute charge immediately, keeps the disks and data intact, and is fully reversible by starting the machine again. There is no capacity risk, no commitment and no performance trade-off, because the machines in scope are already off. It is the rare cost action where doing it can only help.
How do you deallocate safely and keep it fixed?
Work this as one loop: find the stopped machines, confirm none are genuinely needed in a hurry, deallocate them largest first, then prevent recurrence so the saving sticks. None of it is destructive, because deallocating keeps the disks and the machine can be restarted.
1. Inventory every VM by power state
List all VMs with their power state and pick out the ones reading 'VM stopped' rather than 'VM deallocated'. Use the Cost Optimization workbook's 'Virtual Machines in a Stopped State' query or Azure Advisor as a cross-check. Treat this list as the source of truth, because a machine can look off in the portal and still be billing for compute.
2. Confirm nothing genuinely needs instant start on the same host
For the vast majority of stopped machines, deallocating is free of consequence. The only thing you give up is starting instantly on the same physical host and keeping any ephemeral public IP. If a machine truly needs a guaranteed-instant start, that is a capacity-reservation decision, not a reason to keep paying full compute while it is off. For everything else, deallocate.
3. Deallocate, largest compute rate first
Deallocate each stopped machine through the control plane. The compute charge stops on the next billing interval; the disks and data persist. Take the largest VM sizes first, because they carry most of the waste, then sweep up the smaller dev and test boxes. Each machine is a single command and the action is reversible by starting it again.
4. Prevent recurrence with auto-shutdown and a recurring check
Attach an auto-shutdown schedule to dev and test VMs so they deallocate on a timer instead of waiting for someone to remember, and run a recurring power-state check that flags any machine left in the Stopped (not deallocated) state. This is what turns a one-off cleanup into a saving that does not silently refill.
# 1. Deallocate every VM that is stopped but not deallocated (compute still billing).
# 'az vm list -d' populates powerState; 'VM stopped' is the costly state.
az vm list -d \
--query "[?powerState=='VM stopped'].{name:name, rg:resourceGroup}" -o tsv |
while read -r name rg; do
az vm deallocate --resource-group "$rg" --name "$name" --no-wait
echo "$rg/$name: deallocating, compute charge stops on the next billing interval"
done
# 2. Prevent recurrence: attach a daily auto-shutdown schedule (Bicep).
# Save as autoshutdown.bicep and deploy into the VM's resource group.
# The schedule name MUST be shutdown-computevm-<vmName>.
#
# param vmName string
# param location string = resourceGroup().location
# resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' existing = {
# name: vmName
# }
# resource autoShutdown 'Microsoft.DevTestLab/schedules@2018-09-15' = {
# name: 'shutdown-computevm-${vmName}'
# location: location
# properties: {
# status: 'Enabled'
# taskType: 'ComputeVmShutdownTask'
# timeZoneId: 'GMT Standard Time'
# dailyRecurrence: {
# time: '1900'
# }
# targetResourceId: vm.id
# notificationSettings: {
# status: 'Disabled'
# timeInMinutes: 30
# }
# }
# } Quick quiz
Question 1 of 5A VM was shut down from inside the guest OS with 'sudo shutdown now' and shows as 'Stopped' in the portal. What is happening to the bill?
You scored
0 / 5
Keep learning
Go deeper on Azure VM power states, the billing difference and the prevention controls in this capability.
- States and billing of Azure Virtual Machines Microsoft's reference on the Stopped versus Stopped (deallocated) states and exactly when compute is billed.
- Cost Optimization workbook (Azure Advisor) The workbook whose 'Virtual Machines in a Stopped State' query surfaces machines that are stopped but not deallocated.
- Auto-shutdown for Azure VMs How to schedule a VM to shut down automatically, the prevention control that keeps the saving from refilling.
You can now tell the two kinds of off apart: a VM that is Stopped from inside the guest keeps the host reserved and keeps billing for compute, while a deallocated VM releases the host and stops the compute charge. You know how to find every improperly stopped machine with 'az vm list -d' or the Cost Optimization workbook, deallocate them largest first at no trade-off, and stop the problem recurring with auto-shutdown schedules and a recurring power-state check.
Back to the library