Idle virtual machines are instances that run, bill hours and do no work: a test environment after the project, a bastion host nobody logs into, a worker whose queue stayed empty. The saving comes from the compute hours a stopped or deleted instance no longer produces; the rest of its bill, disks and addresses, waits for a second decision. The fix belongs to the team that launched the instance, with a deadline after which the cloud owner stops it.

Symptom

The bill shows instance hours with no load to match. On AWS these are lines with a lineItem/UsageType like EUC1-BoxUsage:m6i.large and lineItem/ProductCode AmazonEC2, whose lineItem/UsageAmount reaches 720 or 744 hours every month. On Azure the lines carry MeterCategory Virtual Machines and a MeterName such as D4s v5, with a Quantity that fills the month. On Google Cloud they are SKUs like N2 Instance Core running in Frankfurt and N2 Instance Ram running in Frankfurt under service.description Compute Engine, with full hours per resource.name. The metrics beside them, CPU and network, stay flat. What separates an idle resource from an orphaned one is set out in idle and orphaned resources; this page covers the instance itself.

An instance that runsand does no workInstance hours fillthe month: BoxUsage,Virtual Machines,Instance Core runningThe metrics beside them,CPU and network,stay flatFull hours withno load to match
Idle shows as instance hours that fill the month while the CPU and network metrics beside them stay flat

How to detect it

The providers' thresholds are the starting point, not the verdict: they find candidates for the team to confirm.

AWS

Console: EC2, Instances, filtered to the running state, then each instance's Monitoring tab; faster is AWS Compute Optimizer, Idle resources. The CLI lists the candidates per region:

aws ec2 describe-instances --filters Name=instance-state-name,Values=running \
  --query 'Reservations[].Instances[].[InstanceId,InstanceType,LaunchTime,Tags[?Key==`Name`].Value|[0]]' \
  --output table

One instance's utilisation over 14 days, as a daily maximum:

aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-0123456789abcdef0 --statistics Maximum \
  --start-time 2026-10-07T00:00:00Z --end-time 2026-10-21T00:00:00Z --period 86400

Two checks AWS runs itself, with documented thresholds (read on 2026-10-21): Trusted Advisor flags an instance with 10 percent or less daily average CPU utilisation and 5 MB or less network I/O on at least 4 of the previous 14 days; Compute Optimizer classifies an instance as idle when peak CPU stays below 5 percent and network I/O below 5 MB per day over 14 days. The CLI fetches the second list:

aws compute-optimizer get-idle-recommendations --filters name=ResourceType,values=EC2Instance

In billing data the candidate is a BoxUsage line with full hours per lineItem/ResourceId and no data transfer line of note growing beside it (AWS Cost and Usage Report).

Azure

Console: Azure Advisor, Cost, the recommendation "Right-size or shutdown underutilized virtual machines". The CLI lists running VMs with their power state:

az vm list -d --query "[?powerState=='VM running'].{name:name, size:hardwareProfile.vmSize, rg:resourceGroup}" -o table

One VM's CPU as a daily maximum over two weeks:

az monitor metrics list --resource <vm-resource-id> --metric "Percentage CPU" \
  --aggregation Maximum --interval P1D --start-time 2026-10-07T00:00:00Z --end-time 2026-10-21T00:00:00Z

Azure Advisor recommends a shutdown when, over the last seven days, the 95th percentile of maximum CPU utilisation is below 3 percent, the maximum of average CPU over the last three days is at most 2 percent and outbound network utilisation is below 2 percent; the lookback can be set to up to 90 days. az advisor recommendation list --category Cost -o table returns the recommendations. In the cost export the candidate is a ResourceId under MeterCategory Virtual Machines with a full Quantity (Azure cost exports).

Google Cloud

Console: Compute Engine, VM instances, the Recommendations column; or the Recommendation Hub. The running instances:

gcloud compute instances list --filter="status=RUNNING" \
  --format="table(name,zone.basename(),machineType.basename(),creationTimestamp)"

The idle VM recommender reads 14 days of CPU and network usage by default and does not publish its thresholds; it skips instances with local SSDs, GPUs or TPUs and GKE nodes. Per zone:

gcloud recommender recommendations list --project=<project-id> --location=<zone> \
  --recommender=google.compute.instance.IdleResourceRecommender --format="table(name.basename(),description,stateInfo.state)"

In the billing export the candidate carries full hours on the Instance Core running and Instance Ram running SKUs per resource.name (Google Cloud billing export).

How to fix it

  1. Find the owner from the tag or the account and send the list with a deadline; an instance without an answer counts as released. Who decides is in the monthly review checklist.

  2. Stop before deleting, as the reversible first step. AWS checks the call with --dry-run before it acts:

    aws ec2 stop-instances --instance-ids i-0123456789abcdef0 --dry-run
    

    Azure has no dry run; az vm deallocate --resource-group <rg> --name <vm> releases the hardware, a shutdown from inside the guest does not. Google Cloud likewise: gcloud compute instances stop <vm> --zone=<zone>.

  3. After a holding period, say 30 days without a question, take a snapshot or image and delete. What keeps billing after the stop, disks, static addresses, licences, is stopped instances that still cost money.

  4. Remove the cause: an environment needed only in office hours gets a schedule (scheduling and auto-scaling); an oversized instance with low load is a case for rightsizing, not for this page.

The effect is immediate: AWS and Google Cloud bill by the second, Azure until the deallocation; the next daily export shows the lower hour count.

yesno: still neededOwner from the tag or theaccount, the list sentwith a deadlineReleased, orno answer?Stop, the reversiblefirst stepKeeps running; an oversizedinstance with low load isrightsizing, not this pageA holding periodwithout a questionSnapshot or image,then deleteRemove the cause: anenvironment needed only inoffice hours gets a schedule
The owner's deadline decides, the stop comes before the delete, and the schedule removes the cause

Risks and side effects

  • Low CPU is not proof of idleness. A licence server, a scheduler, a replica, a warm standby for an outage run almost without load and are still needed. The team's release replaces the threshold.
  • The metrics see only what they measure. Memory and disk I/O are missing from the default metrics; a process waiting for events looks idle.
  • A stopped instance loses its automatically assigned public IPv4 address and the contents of local instance store; AWS documents both, and on Azure a dynamic public IP goes with the deallocation.
  • A commitment stays. A Reserved Instance or a Savings Plan keeps covering the hours whether the instance runs or not; the saving is then only the difference another instance brings under the commitment (commitment coverage and utilisation).
  • Auto Scaling groups replace a stopped instance; there the minimum size is changed, not the instance stopped.

How to verify the saving

Before: the BoxUsage, Virtual Machines or Instance Core running hours per resource id in the last full month. After: the same figure in the first full month after the stop; it has to fall to zero, and the lines that remain for the same resource, disks and addresses, are the second list. The recommender's figure is the "estimated" value; after the team's release "accepted"; after the stop "implemented"; only the following month's invoice turns the difference into a realised saving, as estimated, accepted, implemented, verified sets it out. A commitment shifts the proof: the hours fall, the commitment charge does not, and the commitment's utilisation is the figure that has to show another instance using the coverage set free.

Sources

Read on 2026-10-21. Trusted Advisor cost optimization checks, Compute Optimizer idle resource recommendations, get-idle-recommendations, How EC2 instance stop and start works, Azure Advisor, underutilized virtual machines, Azure VM states and billing, Idle VM recommendations overview, Viewing and applying idle VM recommendations, Recommenders.