Skip to main content

Cut your AWS EBS bill ~20% by migrating gp2 to gp3

· 4 min read
Founder, Dragon Fractal · ex-AWS engineer

Short version: AWS gp3 EBS volumes cost ~20% less per GB than gp2 ($0.08 vs $0.10 per GB-month in us-east-1) and include 3,000 IOPS and 125 MB/s of baseline performance for free. You can convert a volume from gp2 to gp3 online, with no downtime and no snapshot: a single modify-volume call. For most volumes it is free money. Here is how to find them, migrate them, and the one caveat to check.

Why gp3 is cheaper (and usually faster)

gp2 pricing couples performance to size: you get 3 IOPS per GB, so the only way to get more IOPS on gp2 is to over-provision storage you do not need. gp3 decouples them:

gp2gp3
Storage$0.10 / GB-month$0.08 / GB-month (-20%)
Baseline IOPS3 IOPS/GB (burst to 3,000)3,000 included at any size
Baseline throughputscales with size125 MB/s included
Extra IOPS / throughputnot possibleprovision independently

(Prices are us-east-1 list; the ratio holds across regions.)

For a 500 GB volume that is $50/month to $40/month, i.e. $120/year saved, per volume, with equal or better performance. Multiply by every gp2 volume in every account.

Step 1 - Find your gp2 volumes

aws ec2 describe-volumes \
--filters Name=volume-type,Values=gp2 \
--query 'Volumes[].{ID:VolumeId,GiB:Size,AZ:AvailabilityZone,State:State}' \
--output table

Run it per region. EBS is regional, so a volume only shows up in its own region:

for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
echo "== $region =="
aws ec2 describe-volumes --region "$region" \
--filters Name=volume-type,Values=gp2 \
--query 'Volumes[].{ID:VolumeId,GiB:Size}' --output text
done

Step 2 - Migrate (online, no downtime)

Converting the type is a live modify-volume. The volume stays attached and readable/writable the whole time; it briefly enters an optimizing state:

aws ec2 modify-volume --volume-id vol-0abc123def456 --volume-type gp3

To convert everything in a region at once:

for vol in $(aws ec2 describe-volumes \
--filters Name=volume-type,Values=gp2 \
--query 'Volumes[].VolumeId' --output text); do
echo "migrating $vol"
aws ec2 modify-volume --volume-id "$vol" --volume-type gp3
done

No snapshot, no detach, no reboot. (AWS allows one modification per volume per 6 hours, so migrate, then wait before re-modifying the same volume.)

The one caveat: high-IOPS / high-throughput volumes

Because gp2 IOPS scale with size, a large gp2 volume may already deliver more than gp3's 3,000 baseline IOPS. A 2 TB gp2 volume provides 6,000 IOPS; if your workload actually uses them, migrate and provision matching performance on gp3:

aws ec2 modify-volume --volume-id vol-0abc123def456 \
--volume-type gp3 --iops 6000 --throughput 250

The first 3,000 IOPS and 125 MB/s are free; beyond that, extra IOPS are $0.005/provisioned-IOPS-month and extra throughput $0.040/MB/s-month. Even fully matched, gp3 is normally still cheaper than the equivalent gp2, but check CloudWatch VolumeReadOps/VolumeWriteOps before assuming you need the headroom. Volumes ≤ ~1 TB with normal workloads are a straight 20% win.

Do it automatically

Finding gp2 volumes and estimating the savings across every account and region by hand does not scale. That is exactly what Cloud Cost Analyzer's ebs-gp2-to-gp3-migration rule does: it flags every gp2 volume and estimates the monthly saving, alongside 89 other cost rules:

curl -sSL https://releases.dragonfractal.com/install.sh | sh
cca scan --provider aws

The agent runs in your environment with read-only access, so your AWS credentials never leave it. See the AWS setup and required IAM permissions

CLI Reference

  • aws ec2 modify-volume
  • aws ec2 describe-volumes
  • aws ec2 create-snapshot