EC2 Stop vs Terminate: What Actually Happens to Your EBS Data

You stopped your EC2 instance to cut costs over the weekend — but now you're staring at the console wondering whether your data is still there, and whether hitting 'Terminate' by mistake would have ended everything. Understanding the difference between stopping and terminating an EC2 instance is one of those fundamentals that saves you from an irreversible mistake at 2 AM.

TL;DR: EC2 Stop vs Terminate at a Glance

BehaviorStopTerminate
Instance statestopped → can restartshutting-down → terminated (irreversible)
Root EBS volumePersistsDeleted by default (DeleteOnTermination=true)
Additional EBS volumesPersists, stays attachedPersists by default (DeleteOnTermination=false)
Instance store (ephemeral)Data lost on stopData lost on terminate
Elastic IPRetained (associated)Disassociated, not released
Private IPRetainedReleased
Public IP (non-EIP)Released on stop, new IP on startReleased
Billing (instance hours)Stops accruingStops accruing
EBS billingContinuesStops (once volumes deleted)

How EC2 Instance Lifecycle Works

EC2 instances move through a documented state machine. A stop transitions the instance from runningstoppingstopped, preserving the root EBS volume and all attached EBS volumes exactly as they were. The underlying host may change when you restart — AWS may place the instance on different physical hardware — but the EBS volumes reattach because they are network-attached storage, not physically tied to the host. A terminate transitions the instance from runningshutting-downterminated, and this is a one-way door. The instance record eventually disappears from the console after a retention period.

stateDiagram-v2 [*] --> pending : Launch pending --> running : Boot complete running --> stopping : Stop action stopping --> stopped : Host released stopped --> pending : Start action running --> shutting_down : Terminate action shutting_down --> terminated : Cleanup complete terminated --> [*] note right of stopped : EBS volumes persist No compute charges note right of terminated : Root EBS deleted by default Irreversible
  1. running → stopping → stopped: EBS volumes persist. Instance can be restarted. No compute charges accrue.
  2. stopped → pending → running: Instance may land on new physical host. EBS reattaches. A new public IP is assigned (unless Elastic IP is used).
  3. running → shutting-down → terminated: Irreversible. Root EBS deleted by default. Additional EBS volumes survive by default.
  4. Instance store volumes: Data is lost at any transition out of running — both stop and terminate flush ephemeral storage.

The Critical Variable: DeleteOnTermination Flag

Whether your EBS data survives termination is controlled entirely by the DeleteOnTermination attribute on each volume attachment — not by the volume itself. AWS sets this flag to true for the root volume at launch by default, and false for any additional volumes you attach. This asymmetry surprises engineers who assume all volumes behave the same way.

Think of DeleteOnTermination like a sticky note on each volume that says "shred me when the instance dies." The root volume ships with that note pre-attached. Extra volumes don't — but you can add or remove the note at any time.

You can verify the current flag for a running instance before making any decisions:

aws ec2 describe-instances \
  --instance-ids i-0abcdef1234567890 \
  --query 'Reservations[*].Instances[*].BlockDeviceMappings[*].{Device:DeviceName,DeleteOnTermination:Ebs.DeleteOnTermination,VolumeId:Ebs.VolumeId}' \
  --output table

If you want to protect the root volume from deletion on termination, modify the flag while the instance is running or stopped:

aws ec2 modify-instance-attribute \
  --instance-id i-0abcdef1234567890 \
  --block-device-mappings '[{"DeviceName":"/dev/xvda","Ebs":{"DeleteOnTermination":false}}]'

Verify the change took effect:

aws ec2 describe-instance-attribute \
  --instance-id i-0abcdef1234567890 \
  --attribute blockDeviceMapping \
  --query 'BlockDeviceMappings[*].{Device:DeviceName,DeleteOnTermination:Ebs.DeleteOnTermination}'

Stop vs Terminate: What Survives and What Doesn't

EBS-Backed Instances (the common case)

For EBS-backed instances, a stop is safe for your data. The root volume, all attached EBS volumes, and their contents survive intact. What you lose on stop is the in-memory state (RAM contents) and anything written only to instance store. When you restart, the OS boots from the same EBS root volume — your files, installed packages, and configuration are all there.

Instance Store (Ephemeral) Volumes

Instance store volumes are physically attached to the host hardware. The moment an instance stops — or terminates — that data is gone. There is no recovery path. If your workload writes to instance store for performance reasons (scratch space, caches, temporary sort buffers), you must treat that storage as disposable and architect accordingly.

graph TD A["EC2 Instance Action"] --> B{"Action Type?"} B --> C["Stop"] B --> D["Terminate"] C --> E["EBS Root Volume
PERSISTS"] C --> F["EBS Additional Volumes
PERSIST"] C --> G["Instance Store
DATA LOST"] C --> H["RAM / In-memory
DATA LOST"] D --> I{"DeleteOnTermination?"} I --> J["true (root default)
Volume DELETED"] I --> K["false (extra vol default)
Volume PERSISTS"] D --> L["Instance Store
DATA LOST"] D --> M["RAM / In-memory
DATA LOST"] style J fill:#ff6b6b,color:#fff style G fill:#ff6b6b,color:#fff style H fill:#ff6b6b,color:#fff style L fill:#ff6b6b,color:#fff style M fill:#ff6b6b,color:#fff style E fill:#51cf66,color:#fff style F fill:#51cf66,color:#fff style K fill:#51cf66,color:#fff
  1. EBS Root Volume: Survives stop. Survives terminate only if DeleteOnTermination=false.
  2. EBS Additional Volumes: Survive both stop and terminate by default (DeleteOnTermination=false).
  3. Instance Store: Data is lost on both stop and terminate — no exceptions.
  4. RAM / In-memory state: Lost on stop and terminate.

Termination Protection: The Safety Net You Should Enable

AWS provides a termination protection flag that blocks the terminate-instances API call — including accidental clicks in the console. It does not prevent termination triggered by Auto Scaling, Spot interruption, or scheduled actions, but it does protect against human error on standalone instances.

Enable termination protection on an existing instance:

aws ec2 modify-instance-attribute \
  --instance-id i-0abcdef1234567890 \
  --disable-api-termination

Verify it is active:

aws ec2 describe-instance-attribute \
  --instance-id i-0abcdef1234567890 \
  --attribute disableApiTermination \
  --query 'DisableApiTermination.Value'

To terminate a protected instance, you must first disable the protection explicitly — which creates a deliberate two-step process that prevents accidents.

aws ec2 modify-instance-attribute \
  --instance-id i-0abcdef1234567890 \
  --no-disable-api-termination

Experience Signal: The Misdiagnosis That Costs Data

Here is a failure pattern that appears regularly in production: an engineer notices an instance is in stopped state and assumes it was stopped intentionally. They terminate it to clean up "unused" resources. The root volume is gone within seconds — and the application's database, which was running on that root volume without a snapshot, is unrecoverable.

The misdiagnosis: "stopped means unused." The actual cause: the instance was stopped by an automated health check or a scheduled Lambda function, not decommissioned. The fix is two-layered. First, enforce a tagging policy that marks instances with their lifecycle intent (Environment=production, ManagedBy=autoscaling). Second, enable termination protection on any instance that holds stateful data — so that even if someone runs a cleanup script, the API call fails loudly instead of silently succeeding.

The observable signal you missed: the instance had no StateReason indicating user-initiated stop. You can check this after the fact on a stopped instance:

aws ec2 describe-instances \
  --instance-ids i-0abcdef1234567890 \
  --query 'Reservations[*].Instances[*].{State:State.Name,StateReason:StateReason.Message}'

A StateReason of Client.UserInitiatedStop means a human or API call stopped it. Any other reason warrants investigation before you act.

IAM: Separating Stop and Terminate Permissions

The IAM actions for stop and terminate are distinct, which means you can grant operators the ability to stop instances without granting them the ability to terminate. This is a practical least-privilege pattern for teams where junior engineers manage running instances but should not be able to destroy them.

🔽 Click to expand — IAM policy: allow Stop, deny Terminate
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowStopInstances",
      "Effect": "Allow",
      "Action": [
        "ec2:StopInstances",
        "ec2:StartInstances",
        "ec2:RebootInstances",
        "ec2:DescribeInstances",
        "ec2:DescribeInstanceAttribute",
        "ec2:DescribeInstanceStatus"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenyTerminateInstances",
      "Effect": "Deny",
      "Action": "ec2:TerminateInstances",
      "Resource": "*"
    }
  ]
}

Note that ec2:DescribeInstances and related Describe actions require "Resource": "*" — they do not support resource-level restrictions. Verify current IAM support in the EC2 Service Authorization Reference before applying ARN-level restrictions to other actions.

Depth Signal: The Public IP Behavior That Breaks Assumptions

A non-obvious interaction: when you stop an EBS-backed instance that has a non-Elastic public IP, AWS releases that IP back to the pool. When you start the instance again, it receives a different public IP. This is expected and documented — but the failure mode appears when engineers hardcode the public IP in DNS records, firewall allowlists, or third-party webhook configurations. The instance starts successfully, the application is running, but external traffic stops reaching it because the IP changed silently.

The fix is architectural, not operational: assign an Elastic IP to any instance whose address must remain stable across stop/start cycles. An Elastic IP persists through stop and start, and it is not released on termination — it is only disassociated. You continue to incur charges for an Elastic IP that is not associated with a running instance, so release it explicitly after termination if it is no longer needed.

aws ec2 describe-addresses \
  --query 'Addresses[*].{AllocationId:AllocationId,InstanceId:InstanceId,PublicIp:PublicIp,AssociationId:AssociationId}' \
  --output table

Wrap-Up: EC2 Stop vs Terminate — Making the Right Call

The rule is straightforward once the mechanics are clear: stop is a pause, terminate is a deletion. EBS volumes survive both by default — except the root volume, which is deleted on termination unless you explicitly set DeleteOnTermination=false. Instance store data is gone the moment the instance leaves the running state, regardless of whether you stop or terminate.

Before terminating any instance in production, run the describe-instances and describe-instance-attribute commands shown above to confirm the DeleteOnTermination flag and termination protection state. Enable termination protection on stateful instances as a default, not an afterthought.

For further reading, see the official EC2 Instance Lifecycle documentation and the Terminating Instances guide.

Glossary

TermDefinition
EBS (Elastic Block Store)Network-attached persistent block storage for EC2. Survives instance stop and, by default, instance termination for non-root volumes.
Instance StorePhysically attached ephemeral storage on the host. Data is lost when the instance stops or terminates.
DeleteOnTerminationAn EBS volume attachment attribute that controls whether the volume is deleted when the associated instance is terminated.
Elastic IP (EIP)A static public IPv4 address that persists across instance stop/start cycles and is not released on termination.
Termination ProtectionAn instance attribute (DisableApiTermination) that blocks the terminate-instances API call to prevent accidental deletion.

Related Posts

Comments

Popular posts from this blog

EC2 No Internet Access in Custom VPC: Fix Internet Gateway and Route Table

EC2 SSH Connection Timeout: Which Security Group Rules to Check

Difference Between IAM User and IAM Role: Which One Should Your EC2 Use?