Skip to content

How to resize an EC2 instance with minimal downtime (stop-change-start done right)

Resize an EC2 instance by stopping it, changing its type and starting it again, with only a few minutes of downtime. The checks you run first keep a missing driver, a changed public IP or a capacity shortage from turning that short change into an outage.

You can give an EC2 instance, an AWS virtual server, more or less CPU and memory with only a few minutes of downtime. When the disk lives on EBS (Amazon’s network block storage), the process is stop, change the instance type, start again. The resize itself is the easy part. Long outages come from checks people skip beforehand.

Before you stop anything, confirm four things. The new type must work with your AMI, the machine image the instance boots from, and with its drivers. The public IP will change unless you use an Elastic IP, a fixed address AWS lets you keep. Data on instance store, the temporary local disks some types include, is erased at stop. And the new type needs free capacity in your Availability Zone, the AWS data centre location where the instance runs.

What’s happening

The instance type is just an attribute of the instance, but it can only be modified while the instance is stopped, because starting is what places the instance onto a physical host of the new size. That placement step is where the risk lives: the start can fail with InsufficientInstanceCapacity if the target type is scarce in that AZ, and the OS can fail to boot if the AMI lacks the drivers the new hardware expects.

Compatibility is the part worth slowing down for. You cannot cross CPU architectures — an x86 AMI will not start on a Graviton (ARM) type like m7g; that migration is a rebuild, not a resize. Current-generation (Nitro) types require ENA networking drivers and NVMe storage drivers in the OS; any AMI from the last several years has them, but a long-lived instance upgraded in place since the m3/m4 era may not, and it will fail to come up on a Nitro type. Windows and older Linux images are the usual suspects. Also, a stopped instance releases its capacity slot — see what stop actually costs you — so on scarce types the start is not guaranteed to succeed immediately.

What to check first

  • Architecture match. New type and current AMI must both be x86_64 or both arm64. aws ec2 describe-instances --query '...Architecture' settles it.
  • ENA enabled. Required for all current-generation types. Check before you stop, not after the start fails.
  • Instance store volumes. Any data on ephemeral disks is destroyed at stop. If the current or target type has instance store, inventory what lives there.
  • Public IP dependency. No Elastic IP means the public IPv4 changes at stop/start. Find every DNS record, firewall rule, and hardcoded IP pointing at the instance.
  • Stop protection and shutdown behaviour. Disable stop protection if set, and confirm shutdown behaviour is stop, not terminate.

How to verify

Run the compatibility checks in one pass:

# Architecture, ENA support, root device, current type
aws ec2 describe-instances --instance-ids i-0123456789abcdef0 \
  --query 'Reservations[].Instances[].[InstanceType,Architecture,EnaSupport,RootDeviceType,PublicIpAddress]' \
  --output table

EnaSupport must be true and RootDeviceType must be ebs for a clean stop-change-start. Confirm the target type exists in the instance’s AZ:

aws ec2 describe-instance-type-offerings \
  --location-type availability-zone \
  --filters Name=location,Values=ca-central-1a Name=instance-type,Values=m7i.2xlarge

Take a safety snapshot of the root volume (or create an AMI) before touching anything:

aws ec2 create-snapshot --volume-id vol-0123456789abcdef0 \
  --description "pre-resize i-0123456789abcdef0 2026-07-04"

Whether the new size is even the right call is a separate question — Compute Optimizer’s right-sizing signals are worth a look before you buy a bigger box to solve what might be an application problem. Full type-change documentation is at https://docs.aws.amazon.com/ec2/.

The runbook

  1. Announce and schedule the window. A clean resize is three to ten minutes of downtime; commit to a window of thirty so the capacity retry or an OS fsck does not blow the estimate. Do it at the workload’s quietest hour.

  2. Snapshot first. The pre-change snapshot is the difference between “start the old type again” and a real incident if the new type misbehaves.

  3. Stop the instance and wait for stopped. Use the OS to shut down cleanly or aws ec2 stop-instances --instance-ids i-0123456789abcdef0. If it hangs in stopping for more than several minutes, a force stop is available, at the cost of an unclean filesystem.

  4. Change the type. In the console: EC2 > Instances > Actions > Instance settings > Change instance type. CLI:

    aws ec2 modify-instance-attribute \
      --instance-id i-0123456789abcdef0 \
      --instance-type '{"Value": "m7i.2xlarge"}'
  5. Start, and be ready for a capacity retry. aws ec2 start-instances --instance-ids i-0123456789abcdef0. If the start throws InsufficientInstanceCapacity, do not panic and do not revert immediately — retry for a few minutes, then fall back to a sibling size or generation. The full playbook for that error is in InsufficientInstanceCapacity workarounds.

  6. Verify from the inside out. Both status checks green, application ports answering, and the app actually using the new capacity (correct vCPU count and memory visible to the OS). If the public IP changed, update DNS now — this is the step everyone forgets.

  7. Watch for thirty minutes. CPU credit behaviour (if you moved to or from a burstable t family), EBS bandwidth (larger types get more), and application error rates tell you whether the resize did what you hired it to do.

When this is the wrong move

If the instance is in an Auto Scaling group, do not resize it in place — the next scale event or instance replacement reverts your change. Update the launch template’s instance type and roll the group instead; that is what launch templates are for, and an instance-refresh gives you near-zero downtime for free. Same logic for anything behind a load balancer with more than one node: bring up a resized replacement, drain the old node, and skip the downtime window entirely. Stop-change-start is the right tool for singletons — the lone database box, the legacy app server — not for fleets. And if the goal is more disk or faster disk rather than CPU/RAM, resize the EBS volume instead; that is a separate operation that needs no stop at all.

Common mistakes

  • Skipping the ENA/architecture check and discovering at start time that the AMI cannot boot on the new type — now you are debugging in the window instead of before it.
  • Forgetting the public IP changes without an Elastic IP, and spending the downtime window hunting a “network outage” that is just stale DNS.
  • Resizing a t3 into a bigger t3 to fix sustained CPU load, when the real problem is burst credits — a t family at sustained 100% wants an m or c family, not a bigger bucket.
  • Resizing an ASG member by hand and being surprised when the group quietly replaces it with the old type.

Prevention

  • Keep an Elastic IP or DNS name on any singleton people connect to directly, so stop/start never moves the target.
  • Snapshot on a schedule, not just before planned changes — unplanned resizes happen during incidents.
  • Review sizing quarterly with utilization data instead of resizing reactively under load.
  • Keep AMIs current so ENA/NVMe compatibility is never a question.
  • For anything that matters, run two nodes behind a load balancer — then resizes stop being downtime events at all.

The stop-change-start itself is the easy part; the operators who do this well spend ten minutes on checks and three minutes on the change. If nobody on your team truly owns the AWS environment end to end, that is the root of most of these problems — Stack Harbor runs AWS accounts daily under AWS Operations, and you can book an AWS review.