COST OPTIMIZATIONAWS

AWS EBS gp2 to gp3 Migration Guide — Save 20% With Zero Downtime

By Akshay Ghalme·April 8, 2026·10 min read

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

Featuregp2gp3
Base price$0.10/GB/month$0.08/GB/month (20% cheaper)
Baseline IOPS3 IOPS per GiB (min 100, max 16,000)3,000 IOPS free regardless of size
Baseline throughput128–250 MB/s (scales with size)125 MB/s free, scalable to 1,000 MB/s
Max IOPS16,000 (need 5,334 GB volume)16,000 (provision independently)
Burst creditsYes (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

  1. Go to EC2 → Elastic Block Store → Volumes
  2. Select your gp2 volume
  3. Click Actions → Modify volume
  4. Change Volume type to gp3
  5. Set IOPS to 3000 (default, free)
  6. Set Throughput to 125 MB/s (default, free)
  7. 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 StorageMonthly SavingsAnnual 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

  1. List all gp2 volumes
  2. Check current IOPS needs from CloudWatch
  3. Volumes needing < 3,000 IOPS → migrate with defaults
  4. Volumes needing > 3,000 IOPS → provision and calculate cost
  5. Run bulk migration script
  6. Monitor 24–48 hours
  7. Update Terraform to prevent drift
  8. 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.

AG

Akshay Ghalme

AWS DevOps Engineer with 3+ years building production cloud infrastructure. AWS Certified Solutions Architect. Currently managing a multi-tenant SaaS platform serving 1000+ customers.

More Guides & Terraform Modules

Every guide comes with a matching open-source Terraform module you can deploy right away.