Skip to main content
INS // Insights

Unused AMI Snapshot Cost

Updated September 2026 · 10 min read
Unused AMI Snapshot Cost

The CFO sees EBS snapshots as a backup line. The staff engineer owns images. Unused AMI snapshot cost is the storage still attached to machine images nobody launches, especially images a CI job registered last month and never deregistered. Those snapshots often stay hidden from the default snapshot view because they are AMI-backed. Mid-market SaaS on AWS leaks this quietly: every pipeline that bakes an AMI and keeps the last hundred “just in case” pays GB-month on volumes the console does not show as orphaned.

Rutagon builds the cleanup as a job with an allowlist, not a weekend console hunt. The work sits with the AWS cloud infrastructure we already run for accounts, backup vaults, and CI identity. It is not the same as proving restores. If you need the restore-test evidence path, that is AWS Backup restore testing. This article is the bill line for images you do not boot.

Unused AMI Snapshot Cost from CI Image Sprawl

An AMI is a pointer plus one or more EBS snapshots. Deregistering the AMI does not always delete those snapshots. Deleting a snapshot that still backs an AMI fails. The console default snapshot list can hide snapshots that exist only to support AMIs, depending on filters and the “owned by me” view. Staff engineers search Snapshots, see a short list, and tell finance the snapshot line is “backups.” Cost Explorer still shows snapshot storage GB-month.

CI is the usual factory. A packer or image-builder pipeline registers app-main-<sha> on every green build. Launch templates in staging pin an AMI id for a week. Production pins a promoted id. Nobody owns the other ninety images. Shared AMIs to a test account multiply the pointer story across accounts while the snapshots remain in the builder account.

AWS documents AMIs and the snapshot relationship in the EC2 AMI guide. Snapshot storage is billed as EBS snapshot usage, not as a separate “AMI storage” product. We do not quote a per-GB rate. Open Cost Explorer on Elastic Block Store or the snapshot usage type and sort accounts. The builder account is usually the surprise.

Incremental snapshots still occupy space for unique blocks. A chain of daily AMIs from a fat golden image does not cost “one image times thirty.” It costs the unique blocks that changed plus the blocks the chain still references. That is why “we only keep diffs” is not a cleanup strategy. You still need a retention count and a deregister-and-delete job.

Why the Default Snapshot View Lies

The Snapshots console is filtered. AMI-backed snapshots can be excluded unless you show all, search by AMI id, or query the API. Recycle bin and archive tiers add more states. A human looking at the default page is not an inventory.

We inventory from the API in this order: list AMIs owned by the account, describe each image’s block device mappings, collect snapshot ids, then list snapshots and subtract. Snapshots that appear in Cost Explorer but not in the leftover set are either AMI-backed, shared, or in a vault workflow. Snapshots that appear in the leftover set with no AMI and no Backup plan are cleanup candidates after a second check for Terraform state and launch templates.

Launch templates, launch configurations, Batch job definitions, and Auto Scaling still pin AMI ids. A cleanup that deletes a snapshot behind an AMI still referenced by a template is an incident. The job must resolve references before deregister. That is engineering, not a “delete unused” checkbox.

Image Builder and EC2 Image Builder pipelines have their own retention settings. If the pipeline keeps every build and the account also keeps manual AMIs, you have two factories. Pick one owner.

A Retention Contract, Not a Hunt

The contract we ship for mid-market SaaS: production AMIs keep N promoted images per product, named and tagged promote=true. Staging keeps a shorter N. CI scratch images expire on a TTL measured in days, not “until someone notices.” Tags are mandatory at register time: product, pipeline, sha, expires. Untagged register fails the pipeline.

Deregister then delete is a two-step with a delay. Some teams move an AMI to a quarantine tag for a week and only then delete snapshots. That delay is cheaper than restoring a missing golden image from a laptop. It is not an excuse to keep a year of shas.

Shared AMIs need a revoke step. If account B can still launch account A’s image, deleting A’s snapshots breaks B. Organizations that share golden images should treat the share list as part of the inventory.

Public AMIs are a different incident. This article is unused private images. If you find a public AMI you did not intend to publish, that is a security change first and a cost change second.

How We Trace the Snapshot Line

Cost Explorer grouped by account and usage type gets you to the builder account. Then:

aws ec2 describe-images --owners self --query 'Images[].{Id:ImageId,Name:Name,Snaps:BlockDeviceMappings[].Ebs.SnapshotId}'
aws ec2 describe-snapshots --owner-self --query 'Snapshots[].{Id:SnapshotId,Desc:Description}'

Cross the two lists. Anything in the snapshot list that still maps to an AMI you will not launch is unused AMI snapshot cost, even if the Snapshots console hid it. Anything with a description like Created by CreateImage and no AMI is a leftover from a failed or partial deregister.

We put a threshold alarm on that account’s snapshot usage through AWS Cost Anomaly Detection setup. The detector will not name the AMI. The staff engineer still needs the inventory job. The detector stops the “it grew for three months” conversation.

Backup copies in a vault are not this meter in the same way. If the expensive copies are AWS Backup recovery points, do not delete them from the EC2 snapshot console. Coordinate with the backup plan. Restore testing still matters for the copies you keep — again, that is the restore testing path, not a silent delete.

What We Do Not Delete

We do not delete snapshots that AWS Backup manages until the plan says so. We do not deregister the AMI currently in the production launch template. We do not treat “old” as unused without checking shared-account launch history. We do not promise a savings percent. We promise a named list: keep, quarantine, delete, and the snapshot ids that will leave the bill after the delete.

Frequently Asked Questions

Does deregistering an AMI delete the unused AMI snapshot cost?

Not by itself. Deregister removes the AMI pointer, but the EBS snapshots that backed the image often remain and continue to bill as snapshot storage. You must delete those snapshots after you confirm nothing else references them. Always describe the AMI’s block device mappings before and after deregister, because some create-image flows also leave a second snapshot.

Why do I not see AMI snapshots in the default Snapshots console?

The console filters AMI-backed snapshots unless you change the view or query by snapshot id. Cost Explorer still bills them. Use the API: list owned AMIs, collect snapshot ids from block device mappings, then list snapshots. If finance asks why the snapshot line exists while the console looks clean, this filter is the usual reason.

Can we keep every CI AMI for rollback?

You can keep a bounded number of promoted images. Keeping every sha is how unused AMI snapshot cost becomes a standing line. Rollback needs a known-good AMI id in the launch template history, not a museum of packer output. Store the last N promoted ids in the pipeline artifact and delete the rest on a TTL.

Are incremental snapshots cheap enough that retention does not matter?

Incremental billing charges unique blocks, but a long chain of fat images still holds unique data and still bills. A daily AMI for months is not almost free because it is incremental. Inventory the chain, cap N, and delete snapshots after deregister.

If snapshot storage is the line you cannot map to a backup policy, send the Cost Explorer usage types and the builder account id. We will trace the specific bill line — AMI-backed versus leftover — and return a deregister-and-delete job with an allowlist. Call 907-841-8407, email contact@rutagon.com, or use rutagon.com/contact.