AWS EBS gp3 cost migration is one of the few FinOps changes that is both high-confidence and reversible. gp3 unbundles IOPS and throughput from disk size. gp2 bundled them, so teams paid for a 1 TB volume when they only needed 3,000 IOPS on 200 GB of data.
We run this as a two-week scorecard item: inventory, right-size IOPS, modify volumes in place, then prove the bill line moved. It sits next to NAT Gateway cost reduction and CloudFront cost tuning as a bill lever CFOs can feel in one billing cycle.
The Pricing Trap gp2 Built In
gp2 included a baseline of 3 IOPS per GB, bursting to 3,000 IOPS for smaller volumes. That sounded generous until:
- A 1 TB log volume needed 200 GB of capacity and 3,000 IOPS. gp2 made you buy 1 TB to hold the IOPS.
- Throughput was coupled to size. Large sequential jobs paid for unused gigabytes.
- Burst credits ran out on sustained workloads, then latency showed up in the database p99 — which teams "fixed" by growing the volume again.
gp3 starts at 3,000 IOPS and 125 MiB/s at a lower per-GB rate, then you add IOPS and throughput as separate line items. AWS documents the split in the EBS volume types guide. The engineering job is mapping CloudWatch VolumeConsumedReadWriteOps and VolumeThroughputPercentage to a gp3 IOPS/throughput pair that is cheaper than the current gp2 size.
Inventory Before You Click Modify
We never migrate from the console's "gp2 → gp3" suggestion alone. The inventory we pull:
| Signal | Why it matters |
|---|---|
| Volume size vs used filesystem | Size-down candidates vs IOPS-only candidates |
Peak VolumeReadOps / VolumeWriteOps (14 days) | gp3 IOPS provision |
| Peak throughput (MiB/s) | gp3 throughput provision |
| Attachment: root vs data | Root volumes need a maintenance window story |
| Snapshots and Fast Snapshot Restore | Cost side-effects after modify |
| Multi-Attach / io2 | Out of scope for a gp3 cost sprint |
A volume sitting at 2% used with 8,000 IOPS on gp2 is a size-down and type change. A 2 TB warehouse disk already at gp2 baseline IOPS may only need the type change. Mixing those two in one change window is how teams cause an outage and then freeze all FinOps work.
# scorecard snippet: flag gp2 volumes whose 14-day peak IOPS
# would cost less as gp3 at current size
def gp3_cheaper(size_gb: int, peak_iops: int, peak_mib: float) -> bool:
gp2_usd = size_gb * GP2_GB # regional rate from Cost Explorer
iops = max(3000, peak_iops)
mib = max(125.0, peak_mib)
extra_iops = max(0, iops - 3000)
extra_mib = max(0.0, mib - 125.0)
gp3_usd = size_gb * GP3_GB + extra_iops * GP3_IOPS + extra_mib * GP3_MIB
return gp3_usd < gp2_usd * 0.85 # 15% buffer for regional variance
Rates belong in Cost Explorer for the account's region, not in a blog post as a quote. The function is the decision rule; the numbers come from the bill.
In-Place Modify, Not a Copy
EBS ModifyVolume can change gp2 → gp3 without detaching. That is the production path. The constraints we treat as hard:
- One modification at a time per volume. Do not stack a size increase on the same call as a type change unless you have tested the optimization window.
- Optimization time is real. CloudWatch
VolumeTotalReadTimecan wobble while AWS moves extents. We schedule database volumes off peak and watch replica lag. - Nitro vs Xen age. Very old instance families have had modify limitations; we check the instance type before touching attached volumes.
- IOPS headroom on the first modify. We provision to 14-day peak × 1.3, not to the gp2 theoretical max. You can raise IOPS later without another type change.
We do not shrink volumes in the same sprint as a type change. Shrink requires a new volume and rsync or a snapshot restore — that is a different change ticket with a different rollback.
What We Measure After Cutover
A migration that does not move UnblendedCost for AmazonEC2 / EBS:VolumeUsage.gp2 is not done. The scorecard:
- gp2 GB-month → 0 on migrated volumes
- gp3 GB-month + provisioned IOPS + throughput match the model
- Application p99 latency within the pre-change band
- Snapshot storage unchanged (snapshots do not automatically shrink)
If latency regresses, we raise gp3 IOPS — still usually cheaper than growing gp2. That is the whole point of unbundling.
See AWS multi-account cost allocation tagging if you cannot even find EBS spend by team. Tagging is the prerequisite; gp3 is the first mechanical win after tags exist.
A 2-week AWS cost audit is how we turn this into a prioritized fix list → rutagon.com/contact · 907-841-8407 · contact@rutagon.com.
Root Volume Special Case
Root volumes are smaller and noisier. We still migrate them, but we watch instance status checks. Some older AMIs have tools that assumed gp2 burst. If p99 disk latency jumps, raise gp3 IOPS before rolling back the type.
Multi-Attach and io2
If MultiAttachEnabled is true, gp3 may not apply. Inventory first. io2 remains for the few workloads that need it. A cost sprint that converts io2 to gp3 to "save money" is an outage.
Cost Explorer EBS:VolumeUsage.gp2 should fall and gp3 should rise by a modeled amount within one full billing cycle. If gp2 does not fall, you missed volumes in another region or another account.
Frequently Asked Questions
Is every gp2 volume cheaper as gp3?
No. Tiny, idle volumes can be a wash after you count the engineer time. We skip volumes whose modeled savings sit under a threshold and batch the rest. Burst-only gp2 volumes that never exhaust credits are the usual skip list.
Does gp3 migration require downtime?
For a type-only ModifyVolume on a supported instance, AWS does not require a stop. Database owners still pick a window because optimization can add latency. Treat it as a performance change, not a "no-risk checkbox."
What about io1, io2, and st1 volumes?
Different products. io2 is for high-IOPS workloads gp3 cannot reach; st1 is sequential HDD economics. A gp3 sprint that silently converts io2 is a production incident. Inventory volume type first.
Will snapshots get cheaper after gp3?
Not automatically. Snapshot billing is separate. gp3 can reduce the source volume bill; snapshot hygiene is a different cleanup (stale AMIs, unused incremental chains).
How does this relate to Graviton or instance rightsizing?
It is independent. You can migrate EBS type without touching instance family. Combining both in one night is how rollback becomes impossible. Sequence: type change, soak, then instance family — or the reverse, never both.