Stopped instances keep costing money because a stop ends only the compute hours: the disks, the static public addresses, a dedicated host, a commitment and, on Azure, even the instance itself when it was only shut down from inside the guest, all stay on the bill. The saving starts when the instance is released, its disks backed up and deleted and its addresses returned. The fix belongs to the team that stopped the instance and has not decided since whether it still needs it.
Symptom
The bill shows no more instance hours for a resource, but storage and network continue. On AWS these are lines with lineItem/UsageType EUC1-EBS:VolumeUsage.gp3 and EUC1-PublicIPv4:IdleAddress or InUseAddress for a lineItem/ResourceId whose BoxUsage line has gone. On Azure a VM stopped only from the operating system still appears under MeterCategory Virtual Machines with a full Quantity; a deallocated one leaves MeterCategory Storage with Disk meters and MeterCategory Virtual Network with IP Addresses. On Google Cloud the SKUs Storage PD Capacity and Static Ip Charge remain per resource.name while Instance Core running is missing. What a stop ends at each provider is on the instance billing pages; this page names what is left and how to find it.
How to detect it
AWS
What AWS keeps charging after a stop is documented (read on 2026-10-21): no usage or data transfer fees for the instance, but the EBS volumes and every Elastic IP address, associated or not; the automatically assigned public IPv4 address is lost at the stop. Dedicated Hosts are billed per host, with or without running instances, and a Reserved Instance runs on whether the instance runs or not. The stopped instances with their stop reason and volumes:
aws ec2 describe-instances --filters Name=instance-state-name,Values=stopped \
--query 'Reservations[].Instances[].[InstanceId,InstanceType,PlatformDetails,StateTransitionReason,BlockDeviceMappings[].Ebs.VolumeId|join(`,`,@)]' \
--output table
StateTransitionReason carries the time of the stop, such as User initiated (2026-08-03 14:02:11 GMT). The addresses attached to stopped instances:
aws ec2 describe-addresses --query 'Addresses[].[PublicIp,InstanceId,AssociationId]' --output table
Dedicated hosts without instances come from aws ec2 describe-hosts --query 'Hosts[?length(Instances)==0].[HostId,HostProperties.InstanceFamily,State]'. The "Amazon EC2 instances stopped" check in Trusted Advisor lists stopped instances; Compute Optimizer reports their volumes as Unattached only after 32 days without an instance, which a stopped instance never reaches. In billing data the case shows as EBS:VolumeUsage without BoxUsage for the same resource in the same month (AWS Cost and Usage Report).
Azure
Azure has two states, and only one saves: "Stopped" after a shutdown from inside the guest leaves the VM allocated on its host and billed; "Stopped (deallocated)" after az vm deallocate releases the hardware and ends compute billing, while disks and networking continue (VM states and billing). Both states at a glance:
az vm list -d --query "[?powerState=='VM stopped' || powerState=='VM deallocated'].{name:name, state:powerState, size:hardwareProfile.vmSize, rg:resourceGroup}" -o table
The disks and public addresses attached to those VMs:
az disk list --query "[?managedBy!=null].{disk:name, vm:managedBy, sku:sku.name, gb:diskSizeGb}" -o table
az network public-ip list --query "[].{name:name, alloc:publicIPAllocationMethod, sku:sku.name, attached:ipConfiguration.id}" -o table
Azure Advisor has no recommendation of its own for stopped VMs; its underutilised VM recommendation covers running ones. In the cost export a VM stopped from the guest shows as a full Quantity under Virtual Machines with flat metrics, a deallocated one as Storage and IP Addresses rows without a Virtual Machines row (Azure cost exports).
Google Cloud
A stopped Compute Engine instance is in TERMINATED and keeps billing the disks, disk snapshots and external IP addresses that stay attached to it (Stop and start an instance). A suspended one is in SUSPENDED: its memory is saved to persistent storage and counts against the persistent disk quota, and after 60 days Compute Engine moves it to TERMINATED itself (Suspend and resume an instance). Both states with their disks:
gcloud compute instances list --filter="status=(TERMINATED,SUSPENDED)" \
--format="table(name,zone.basename(),status,lastStopTimestamp,disks[].deviceName.list())"
The reserved external addresses, assigned or not:
gcloud compute addresses list --format="table(name,region.basename(),address,status,users.list())"
The idle IP address recommender, google.compute.address.IdleResourceRecommender, and the idle persistent disk recommender, google.compute.disk.IdleResourceRecommender, find the leftovers once the instance is deleted rather than stopped (Recommenders). In the billing export the case carries Storage PD Capacity and Static Ip Charge without Instance Core running for the same resource.name (Google Cloud billing export).
How to fix it
- Record the stop time and the owner for every stopped instance; one stopped longer than the cost policy allows, say 30 days, goes on the deletion list.
- On Azure correct the state first:
az vm deallocate --resource-group <rg> --name <vm>turns a VM that was only shut down into a deallocated one. That alone ends compute billing. - Back up, then delete. AWS: an image or a snapshot per volume, then
aws ec2 terminate-instances --instance-ids i-0123456789abcdef0 --dry-run, without--dry-runonly after the release; the root disk goes with the instance whenDeleteOnTerminationis set, data volumes stay and needaws ec2 delete-volume --volume-id vol-0123456789abcdef0 --dry-run. Addresses go back withaws ec2 release-address --allocation-id eipalloc-0123456789abcdef0 --dry-run. Azure:az vm deleteremoves only the VM, disks and addresses stay;az disk deleteandaz network public-ip deletefollow without a dry run, so only against the checked list. Google Cloud:gcloud compute instances delete <vm> --zone=<zone>asks what to do with the disks;gcloud compute addresses deletereleases an address. - Remove the cause: instances that are stopped regularly get a schedule with deletion at expiry (scheduling and auto-scaling), and
DeleteOnTerminationor Azure's delete option for OS disks belongs in the template new instances come from.
The compute saving of step 2 takes effect at once; the storage and address saving of step 3 appears in the daily export after the deletion.
Risks and side effects
- A stopped instance is often a backup nobody called one. A snapshot or image has to exist before the deletion, and a restore has to have been rehearsed once; old snapshots and machine images says how long those then stay.
- A released Elastic IP address or a dynamic Azure address does not come back. DNS records, firewall rules at customers and allow lists at partners keep pointing at the old address.
- A Dedicated Host or a commitment saves nothing through the deletion of the instance; there the question is whether the host is released or the commitment steered to other instances (commitment coverage and utilisation).
- Licences follow different rules: a Windows licence included in the instance price ends with the hours, a licence you brought does not, and a marketplace fee per hour ends with the instance, a subscription does not (forgotten marketplace subscriptions and licence fees).
- An instance restarted after a long stop lacks security updates, and on Google Cloud a suspended instance terminated after 60 days has lost its memory state.
How to verify the saving
Before: per resource id, the lines that remained after the stop, EBS:VolumeUsage and PublicIPv4, the Storage and IP Addresses rows, Storage PD Capacity and Static Ip Charge, as the amount of the last full month. After: the same lines in the first full month after the deletion, expected zero, and on Azure also the Virtual Machines row, which has to disappear after the deallocation. The amount of the deletion list is the estimate; the team's consent makes it accepted; the deletion implemented; the following month's invoice realises it, as estimated, accepted, implemented, verified sets out. A snapshot kept in place of the disk is a new line; the proof nets it off.
Sources
Read on 2026-10-21. How EC2 instance stop and start works, Elastic IP addresses, Trusted Advisor cost optimization checks, Compute Optimizer idle resource recommendations, Azure VM states and billing, Stop and start a Compute Engine instance, Suspend and resume an instance, Recommenders.