AWS EBS gp2 to gp3 Migration Guide — Save 20% With Zero Downtime
gp3 is 20% cheaper than gp2 by default, delivers 3,000 IOPS baseline (vs gp2’s size-dependent scaling), and lets you independently scale IOPS and throughput. Migrating is free, takes minutes, requires zero downtime, and there’s almost no reason NOT to do it. This guide covers three methods: AWS Console, CLI (with a bulk migration script), and Terraform.
gp2 vs gp3 — What Actually Changed
| Feature | gp2 | gp3 |
|---|---|---|
| Base price | $0.10/GB/month | $0.08/GB/month (20% cheaper) |
| Baseline IOPS | 3 IOPS per GiB (min 100, max 16,000) | 3,000 IOPS free regardless of size |
| Baseline throughput | 128–250 MB/s (scales with size) | 125 MB/s free, scalable to 1,000 MB/s |
| Max IOPS | 16,000 (need 5,334 GB volume) | 16,000 (provision independently) |
| Burst credits | Yes (small volumes) | Not needed (high baseline) |
A 100 GB gp2 volume gets only 300 IOPS. The same size gp3 gets 3,000 IOPS — 10x more for 20% less money.
When NOT to Migrate
Edge case: a very large gp2 volume (over 1 TB) relying on size-based IOPS. A 5,334 GB gp2 gets 16,000 IOPS included. On gp3, you’d pay $65/month extra for provisioned IOPS above 3,000. Do the math — for 95%+ of workloads, gp3 still wins.
Method 1: AWS Console
- Go to EC2 → Elastic Block Store → Volumes
- Select your gp2 volume
- Click Actions → Modify volume
- Change Volume type to
gp3 - Set IOPS to
3000(default, free) - Set Throughput to
125MB/s (default, free) - Click Modify → Confirm
The volume enters “optimizing” state but remains fully usable. No reboot, no detach, no downtime.
Method 2: AWS CLI (Bulk Migration)
Single volume:
aws ec2 modify-volume --volume-id vol-0abc123def456 --volume-type gp3 --iops 3000 --throughput 125
Bulk migrate all gp2 volumes in a region:
#!/bin/bash
VOLUMES=$(aws ec2 describe-volumes --filters Name=volume-type,Values=gp2 --query 'Volumes[*].VolumeId' --output text)
COUNT=0
for VOL_ID in $VOLUMES; do
echo "Migrating $VOL_ID to gp3..."
aws ec2 modify-volume --volume-id "$VOL_ID" --volume-type gp3 --iops 3000 --throughput 125
if [ $? -eq 0 ]; then
COUNT=$((COUNT + 1))
fi
sleep 1
done
echo "Migrated $COUNT volumes."
Check status:
aws ec2 describe-volumes-modifications --filters Name=modification-state,Values=modifying,optimizing --query 'VolumesModifications[*].[VolumeId,ModificationState,Progress]' --output table
Method 3: Terraform
For standalone EBS volumes:
resource "aws_ebs_volume" "data" {
availability_zone = "ap-south-1a"
size = 100
type = "gp3" # was "gp2"
iops = 3000
throughput = 125
tags = { Name = "app-data" }
}
For EC2 root volumes:
resource "aws_instance" "app" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.medium"
root_block_device {
volume_size = 30
volume_type = "gp3"
iops = 3000
throughput = 125
}
}
For ASG launch templates:
resource "aws_launch_template" "app" {
block_device_mappings {
device_name = "/dev/xvda"
ebs {
volume_size = 30
volume_type = "gp3"
iops = 3000
throughput = 125
}
}
}
terraform plan shows an in-place update — no instance replacement.
Calculating Your Savings
Formula: monthly_savings = total_gp2_GB × $0.02
Find total gp2 storage:
aws ec2 describe-volumes --filters Name=volume-type,Values=gp2 --query 'sum(Volumes[*].Size)' --output text
| Total gp2 Storage | Monthly Savings | Annual Savings |
|---|---|---|
| 100 GB | $2 | $24 |
| 500 GB | $10 | $120 |
| 1 TB | $20 | $240 |
| 5 TB | $100 | $1,200 |
| 10 TB | $200 | $2,400 |
Verifying the Migration
aws ec2 describe-volumes --volume-ids vol-0abc123def456 --query 'Volumes[0].[VolumeType,Iops,Throughput,State]' --output text
Monitor CloudWatch for 24–48 hours: VolumeReadOps, VolumeWriteOps, VolumeQueueLength (should stay below 1).
What About RDS?
RDS uses EBS under the hood. Same savings apply:
resource "aws_db_instance" "main" {
storage_type = "gp3" # was "gp2"
allocated_storage = 100
iops = 3000
}
Migration Checklist
- List all gp2 volumes
- Check current IOPS needs from CloudWatch
- Volumes needing < 3,000 IOPS → migrate with defaults
- Volumes needing > 3,000 IOPS → provision and calculate cost
- Run bulk migration script
- Monitor 24–48 hours
- Update Terraform to prevent drift
- Migrate RDS storage types too
Frequently Asked Questions
Is there downtime during gp2 to gp3 migration?
No. Fully online, zero downtime. No reboot or detach required.
Can I go back from gp3 to gp2?
Yes, same modify process. But gp3 is cheaper and faster — there’s rarely a reason to.
Does migration affect my data?
No. It’s a metadata change, not a data migration. Your data stays intact.
How long does optimization take?
Minutes for small volumes, hours for very large ones. Volume is fully usable throughout.
Should I migrate io1/io2 to gp3?
Only if you need fewer than 16,000 IOPS. io1/io2 support up to 64,000 IOPS.