RDS (non-Aurora)
Storage Type and Volume Size Are a Cost Decision You Make Once
- gp3 vs. io1 cost gap is ~4.4x at equivalent provisioned IOPS ($0.115/GB + $0.02/IOPS vs. $0.125/GB + $0.10/IOPS) — not a rounding difference, a default-changing one; io2 bills at the same flat rate as io1 on RDS (confirmed via AWS's launch announcement), so the same ~4.4x gap applies to io2 as well
- io2 Block Express is the only tier with a 99.999% durability SLA and sub-millisecond target latency — io1 doesn't clear that bar despite also being "Provisioned IOPS"
- Striping threshold (400GB open-source / 200GB Oracle) quadruples baseline performance for free — but crossing it under load costs hours of degraded I/O during re-striping
- Storage only scales up — the billing baseline you cross into is permanent, with no shrink path
- SQL Server doesn't support striping at all — this lever doesn't exist on that engine, so its storage-cost curve doesn't have this same inflection point
Production premise
RDS storage is not a single billing line. You pick a storage type and a volume size per instance, and the two storage families price IOPS in completely different ways.
gp3 is the default family. It bundles a free baseline of 3,000 IOPS and 125 MiB/s into the base storage rate, which is $0.115/GB-month on RDS. That is a distinct, higher rate than EBS gp3's $0.08/GB-month; RDS storage is a different service entirely. Above the baseline, gp3 charges $0.02 per additional provisioned IOPS-month.
Provisioned IOPS io1 has no free baseline at all. Every IOPS is billed from zero, at $0.10/IOPS-month, on top of a higher base storage rate of $0.125/GB-month.
Run the numbers at 10,000 IOPS on a 1TB volume. gp3 costs roughly $255/month: $115 for storage plus $140 for the 7,000 IOPS above its free baseline. io1 costs roughly $1,125/month: $125 for storage plus $1,000 for all 10,000 IOPS billed from zero. The identical IOPS number prices out about 4.4x apart, because io1 charges for every IOPS instead of just the ones above the free tier.
io2 Block Express bills at the identical flat rate to io1 on RDS. AWS's own launch announcement confirms it: "io1 volumes and io2 Block Express storage volumes are billed at the same rate." So io2's extra durability and latency come at no per-IOPS premium here. This differs from EBS's io2, which uses tiered per-IOPS pricing that doesn't apply to RDS.
Failure mode & inflection point
One failure is provisioning io1 or io2 out of habit. It was once the safe recommendation, and plenty of templates still default to it. The workload never actually needed io2 Block Express's sub-millisecond latency or its 99.999% durability SLA, and the bill never comes back down.
The inverse failure comes from the storage system itself. On open-source engines, a volume that grows across the 400GB threshold (200GB for Oracle) triggers automatic 4-way EBS striping. That is usually a win: the baseline jumps from 3,000 to 12,000 IOPS and from 125 to 500 MiB/s, for free.
But if the crossing happens mid-migration or during a live cutover, the re-striping process itself can degrade I/O latency for several hours while it completes. And because RDS storage only ever scales up, whatever baseline cost you cross into is permanent. There is no shrink path to walk it back.
Production guardrail
Default to gp3 for essentially every workload. At equivalent provisioned IOPS, the ~4.4x cost gap over io1 is too large to justify without a specific reason.
One factor overrides the default: a documented latency SLA that genuinely requires io2 Block Express's sub-millisecond target and 99.999% durability. When that applies, choose io2 over io1 outright. They bill at the identical rate on RDS, so io2's better durability (99.999% vs. io1's 99.8–99.9%) and IOPS ceiling come at no cost premium. Once you are past the gp3-versus-provisioned-IOPS decision, there is no scenario where io1 is the better pick. Absent that documented requirement, provisioning io1 or io2 is close to always the wrong call.
Separately: if you are on an open-source engine and expect to cross 400GB eventually (200GB on Oracle), cross it during a planned maintenance window rather than organically under load. You get the free 4x IOPS and throughput bump without eating the re-striping penalty during a period that matters.