DEV Community

Muskan Bandta
Muskan Bandta

Posted on

The Cloud Zombie Index: Unattached EBS Volumes, Orphaned Snapshots, Unused Elastic IPs and Incomplete Multipart Uploads

Every cloud account is haunted. Not by anything dramatic, just by resources that outlived whatever created them and now bill you every hour for nothing. I call them cloud zombies: things nobody owns, nobody uses, and nobody remembers, quietly draining the budget. They are the cheapest waste to kill because deleting them breaks nothing, and the easiest to ignore because none of them is big on its own.

Here is a field guide to the most common zombies, how to find each, and how to kill them safely.

1. Unattached EBS volumes

When you terminate an EC2 instance, its data volumes do not always go with it. Volumes with "delete on termination" off survive, detached, billing per GB forever. A 500 GB gp3 volume nobody has touched in a year is pure waste.

Find them:

aws ec2 describe-volumes --filters Name=status,Values=available \
  --query "Volumes[].{ID:VolumeId,GB:Size,Created:CreateTime}" --output table
Enter fullscreen mode Exit fullscreen mode

status=available means "not attached to anything." Snapshot first if you are unsure, then delete.

2. Orphaned EBS snapshots

Snapshots pile up from old backup scripts and long-gone volumes. The dangerous ones to delete are snapshots referenced by an AMI, so check before you purge. Everything older than your retention policy that is not backing an AMI is a candidate. This is usually the single largest zombie category by count.

3. Unused Elastic IPs

This one actively bills you because it is idle. AWS charges for an Elastic IP that is allocated but not associated with a running instance. An idle EIP is a rare case of paying specifically for not using something.

aws ec2 describe-addresses \
  --query "Addresses[?AssociationId==null].{IP:PublicIp,Alloc:AllocationId}" --output table
Enter fullscreen mode Exit fullscreen mode

Release any that come back, after confirming nothing plans to use them.

4. Incomplete multipart uploads

The sneakiest zombie. When a large S3 upload fails partway, the uploaded parts are not automatically cleaned up. They sit in the bucket, invisible in the normal object listing, billing you for storage indefinitely. Entire teams have gigabytes of these they have never seen.

The fix is a lifecycle rule that aborts incomplete multipart uploads after a few days:

{
  "Rules": [{
    "ID": "abort-incomplete-mpu",
    "Status": "Enabled",
    "Filter": {},
    "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 7 }
  }]
}
Enter fullscreen mode Exit fullscreen mode

Set this on every bucket. It is a one-time fix that stops a category of invisible waste forever.

5. The cross-cloud cousins

The same pattern repeats everywhere:

  • Azure: unattached managed disks (they bill exactly like unattached EBS volumes), orphaned snapshots, unassociated public IPs.
  • GCP: orphaned persistent disks, unused static external IPs, old machine images.
  • Everywhere: load balancers with no healthy targets, abandoned node groups, idle dashboards and alarms.

How to run a sweep without breaking anything

The reason people avoid this cleanup is fear of deleting something that matters. Two rules make it safe:

  1. Snapshot before delete, by default. For anything with data (volumes, disks), take a snapshot first. Storage for a snapshot is cheap; restoring from one is easy. This turns "delete" from irreversible into reversible.
  2. Age plus unattached, not just unattached. Only target resources that are both detached/unassociated and older than some threshold (14 to 30 days). This avoids catching something created an hour ago mid-setup.

Run it as a monthly habit, not a one-time heroic cleanup. Zombies regenerate: every terminated instance, failed upload, and decommissioned service can leave one behind. A recurring sweep (a scheduled Lambda, or a tool that does discovery and flags orphans automatically, which is part of what ZopNight handles) keeps the account clean instead of letting it silt up again.

The take

None of these zombies is a big number by itself. Collectively, on a neglected account, they are routinely thousands of dollars a month, and they are the safest savings you will ever book because deleting them breaks nothing. Build the "cloud zombie index" for your account this week: unattached volumes, orphaned snapshots, idle EIPs, incomplete multipart uploads, and their cross-cloud cousins. Snapshot, age-filter, delete, repeat monthly.

What is the biggest zombie you have found, and how long had it been billing before anyone noticed? Mine was a set of orphaned snapshots from a backup script that had been "temporary" for three years.

Top comments (0)