All cheat sheets
Storagecheat sheet

EBS DeleteOnTermination

The wrong default on secondary EBS volumes leaves orphaned storage billing forever after instances terminate. One boolean in your launch templates stops the bleed; one audit command finds what already leaked.

Last reviewed: July 11, 2026

TL;DR: When an EC2 instance terminates, its root volume is deleted — but any additional volume defaults to DeleteOnTermination=false and lives on, invisible and billing, in "available" state. AWS never reminds you. Auto Scaling groups mass-produce these orphans. The fix is one boolean in your launch templates, plus a one-time sweep of what already leaked.

The numbers

  • Ten forgotten 100 GB gp3 volumes: 10 × 100 × $0.08 = $80/month, $960/year — and that's a small shop.
  • Teams with ASG churn routinely accumulate hundreds of orphans; real-world cleanups in the digest's source workflow dropped $400/month (startup, 40 orphans) and $2,000+/month (enterprise, 200+ orphans).
  • Snapshots as a safety net cost ~$0.05/GB-month incremental — cheaper than keeping full volumes around "just in case."

Do this

  1. Sweep existing orphans:

    aws ec2 describe-volumes --filters Name=status,Values=available \
      --query 'Volumes[].{id:VolumeId,size:Size,created:CreateTime,tags:Tags}'
    

    Triage by age and tags. Snapshot anything questionable, then delete. (Volumes older than 30 days with no owner tag are almost always dead weight.)

  2. Stop making new ones — fix the source. In launch templates / Terraform / CloudFormation, set the flag on every non-stateful secondary volume:

    ebs_block_device {
      device_name           = "/dev/sdf"
      delete_on_termination = true
    }
    
  3. Fix already-running instances live (no reboot needed):

    aws ec2 modify-instance-attribute --instance-id i-0abc... \
      --block-device-mappings \
      '[{"DeviceName":"/dev/sdf","Ebs":{"DeleteOnTermination":true}}]'
    
  4. Find the future orphans before they happen — attached volumes whose flag is off:

    aws ec2 describe-instances --query 'Reservations[].Instances[].
      BlockDeviceMappings[?Ebs.DeleteOnTermination==`false`]'
    
  5. Enforce it so it stays fixed: an AWS Config custom rule or a tfsec/OPA check in CI that flags non-prod instances launching with the flag off. Engineers forget; automation doesn't.

Gotchas

  • The asymmetric default: root volume deletes, secondary volumes don't. That's deliberate on AWS's part ("don't destroy user data") — the cost of the caution is yours.
  • No notifications exist. No email, no console nag. The only signal is the bill.
  • Deregistering an AMI does not delete its snapshots — a related leak worth sweeping in the same audit.
  • Blanket true is dangerous on stateful workloads. Decide by role, not by account.

Skip this if

…the volume genuinely should outlive its instance:

  • Self-managed databases on EC2 (Postgres, Kafka, Elasticsearch) — termination shouldn't kill the data store; use snapshots/AWS Backup for lifecycle instead.
  • Detach-and-reattach patterns (some blue/green deployments move a data volume to the new instance).
  • Any data that can't be rebuilt and where a snapshot isn't an acceptable recovery path.

For everything else — dev, test, CI, stateless app servers — the flag should be true.

Run this audit with your AI assistant

Paste this into Claude, ChatGPT, or any agent that can run the AWS CLI with read-only credentials. It audits your account for exactly the waste this sheet describes — and changes nothing.

You are auditing an AWS account for orphaned and orphan-prone EBS volumes.
Use the AWS CLI with READ-ONLY credentials. Do not create, modify, or
delete anything — report findings and recommended (unapplied) fixes only.

1. Existing orphans (per region in use):
   aws ec2 describe-volumes --filters Name=status,Values=available
   For each: id, size, type, created date, tags. Cost ≈ size × $0.08/mo
   (gp3) or $0.10/mo (gp2).
2. Future orphans — attached volumes that will survive termination:
   aws ec2 describe-instances --query 'Reservations[].Instances[].
   {id:InstanceId,name:Tags[?Key==`Name`]|[0].Value,maps:BlockDeviceMappings}'
   Flag every non-root mapping with Ebs.DeleteOnTermination == false.
   Cross-reference instance tags (env=dev/test/ci → almost certainly
   should be true; database/stateful roles → false is legitimate).
3. Launch templates and ASGs: aws ec2 describe-launch-template-versions
   (default+latest) — flag templates whose block device mappings omit or
   disable DeleteOnTermination on secondary volumes.

Report: (a) orphan table (volume | age | size | est. $/mo | last-known
purpose from tags) with total monthly waste; (b) at-risk table of
attached volumes with the flag off, grouped by workload type;
(c) recommended launch-template/IaC fixes and the modify-instance-attribute
commands for review — but do NOT execute them. Remind me to snapshot
anything questionable before deleting orphans.
Works with any assistant that can run shell commands.

Want the guided version?

The EBS DeleteOnTermination walkthrough covers this topic interactively — it asks about your setup, branches to what’s relevant, and quizzes you on the tricky parts. Free and anonymous.

Start the walkthrough