Cut your AWS EBS bill ~20% by migrating gp2 to gp3
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:
| gp2 | gp3 | |
|---|---|---|
| Storage | $0.10 / GB-month | $0.08 / GB-month (-20%) |
| Baseline IOPS | 3 IOPS/GB (burst to 3,000) | 3,000 included at any size |
| Baseline throughput | scales with size | 125 MB/s included |
| Extra IOPS / throughput | not possible | provision 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-volumeaws ec2 describe-volumesaws ec2 create-snapshot