Idle Azure VMs: the servers that have been thinking about it since 2021
Somewhere in your estate is a virtual machine called something like
vm-demo-prospect in a resource group called rg-poc-2022. It was built for a
customer presentation. The presentation happened. The customer did not sign. The
VM has been running for three and a half years at roughly the price of a
streaming subscription per week, and nobody has switched it off because nobody
is certain what it does.
Idle azure vms are harder than orphaned disks for exactly that reason. An unattached disk has no user. A quiet VM might have one person who runs one thing on it once a quarter, and that person will find you.
Defining idle azure vms with metrics rather than instinct
"Nobody uses it" is not a finding, it is a hunch. Three metrics over a window of 14 to 30 days will turn it into something you can put in a ticket.
CPU percentage. The obvious one, and the least reliable on its own. A busy idle machine is a real thing: antivirus scans, patch agents and monitoring consume CPU on a box doing nothing useful.
Network in and out. More telling. A server nobody connects to has a characteristic profile: small, regular blips from agents phoning home, and nothing else. If network traffic never exceeds a few kilobytes outside a five-minute window each hour, the only thing talking to that machine is your own monitoring.
Disk operations per second. The tiebreaker. A machine running a real workload writes something. Logs, temporary files, a database checkpoint. A machine at genuinely zero write IOPS for a fortnight is not doing work.
Take all three together and the picture is usually unambiguous. Microsoft's monitoring documentation for virtual machines covers which metrics are available without an agent, which matters because half the candidates will not have one installed.
A 14 day window catches weekly patterns. A 30 day window catches monthly ones, which is what you want before touching anything that might be a month-end job.
Stopped is not the same as deallocated
This one costs people real money, and the portal does not help.
A VM in the Stopped state has been shut down from inside the guest operating system. Azure is still holding the compute reservation for it, and you are still paying for it. From the guest's point of view it is off. From the bill's point of view very little has changed.
A VM in the Stopped (deallocated) state has released its compute. You stop paying for the compute. You carry on paying for the disks, because the disks still exist and managed disks bill from creation to deletion regardless of what is attached.
So "we turned that server off last year" and "that server costs nothing" are different statements, and the gap between them is the entire compute charge. Microsoft's VM power states documentation sets out which states bill and which do not, and it is worth reading once properly.
The practical consequence: when you audit for idle machines, check power state as well as metrics. A machine sitting in Stopped rather than deallocated is free money, because somebody already decided they did not need it and the saving was never realised.
Auto-shutdown, and why it gets removed
Dev/test boxes should not run overnight. Azure has a built-in auto-shutdown schedule on the VM blade, and DevTest Labs has a richer version, and both work.
The reason they end up disabled is always the same. Somebody was working late, the machine shut down under them, they lost what they were doing, and they turned the schedule off rather than turning it back on the next morning. If you are introducing auto-shutdown to machines other people use, the notification webhook and the grace period matter more than the schedule.
Start with the boxes nobody is emotionally attached to: build agents, scratch
environments, anything with poc or demo in the name.
What to check before switching anything off
Deallocating a machine that turns out to matter is a worse afternoon than leaving it running for another month. Five checks, in order of how often they save me.
Who created it. The activity log holds creation events for 90 days. Beyond that, tags if you have them, which is the argument for a tagging strategy that survives.
What talks to it. NSG flow logs if enabled, or just the network metrics. An inbound connection from one internal address at 03:00 on the first of the month is a scheduled job, not noise.
Whether it is in a backup or replication policy. A machine somebody set up Site Recovery for was important to somebody.
Whether anything references its name. A DNS record, a connection string in App Configuration, a hardcoded hostname in a script. This is the one that catches people.
What it would cost to be wrong. Deallocate rather than delete, leave it for a fortnight, and see who shouts. Deallocated machines can be started again in minutes and cost only their disks in the meantime.
That last one is the whole technique. Deallocation is a reversible experiment with a measurable saving, and it converts an argument about whether a machine is needed into an observation.
There is a variant worth knowing for the machines nobody will authorise you to touch. Deallocate on a Friday evening and start it again on Monday morning, on a schedule, for a month. If nothing breaks and nobody notices, you have a month of evidence rather than an opinion, and the saving is already banked while the conversation happens. If something does break, it broke on a weekend with a five minute fix, which is the cheapest possible way to learn that a machine matters.
Where this fits
Idle machines are the second thing to look at after orphaned resources, and in that order for a reason. Orphans have no owner to consult, so they are pure administrative work. Idle machines need a conversation, and conversations are easier once you have already saved the company something.
The AzClean Toolkit includes the idle VM check alongside the orphan sweep, with the metric window as a parameter so you can run 14 days for a quick look and 30 for the version you act on.