AWS Storage Cost Optimization: The Complete Guide to EBS, Aurora & S3 (2026)

By Bill Gleeson · Updated July 2026
Storage is usually 20–30% of an AWS bill, and it’s the part with the cleanest, lowest-risk savings on the platform. Almost every account is overpaying in the same few ways: GP2 volumes where GP3 would cost less and perform better, expensive provisioned-IOPS (io1/io2) storage that almost no workload actually needs, Aurora databases paying per-request for I/O they could get flat-rate, and S3 buckets where objects sit in Standard for years untouched.
This guide compares every storage option that matters for cost, gives you the break-even math, and links out to the deep-dive on each. If you only read one table, read the decision framework near the bottom.
What this guide covers
- EBS volumes: GP2 vs GP3 vs io1 vs io2 — the master comparison
- The #1 win: GP2 → GP3 (~20% cheaper, 10× the IOPS on small volumes)
- Drop io1/io2 for GP3 (60–87% cheaper; rarely needed)
- RDS storage: io1/io2 → GP3 (cut IOPS cost up to 60%)
- Aurora: Standard vs I/O-Optimized (30–40% off for I/O-heavy workloads)
- S3: Intelligent-Tiering (up to 68%; and when it’s a trap)
- OpenSearch and managed-service EBS markups (15–20%)
- Decision framework: which storage should I use?
The AWS storage hierarchy: where the money goes
Block storage (EBS) is the biggest single line for most accounts, followed by object storage (S3) and database storage (Aurora/RDS). The cost levers are different for each, but the principle is the same: you are almost always paying for a performance tier you don’t use. GP2 charges you for storage to indirectly buy IOPS. io1/io2 charges per provisioned IOPS whether you use them or not. Aurora Standard charges per I/O request. Each has a cheaper alternative that gives equivalent or better performance for typical workloads.
EBS volumes: GP2 vs GP3 vs io1 vs io2
EBS is where most storage waste lives. Here’s the full comparison (indicative us-east-1 list pricing — verify in your region):
| Volume type | Class | Storage $/GB-mo | IOPS | IOPS pricing | Max throughput | When to use |
|---|---|---|---|---|---|---|
| gp2 | SSD | $0.10 | 3 IOPS/GB (burst to 16K) | Bundled in storage price | Up to 250 MiB/s | Legacy — migrate to gp3 |
| gp3 | SSD | $0.08 | 3,000 baseline, up to 16,000 | 3,000 free, then $0.005/IOPS | 125 MiB/s baseline, up to 1,000 | Default for ~95% of workloads |
| io1 | SSD | $0.125 | Up to 64,000 | $0.065/provisioned IOPS | Up to 1,000 MiB/s | Rare — sub-ms latency needs |
| io2 / io2 Block Express | SSD | $0.125 | Up to 256,000 | $0.065/provisioned IOPS | Up to 4,000 MiB/s | Mission-critical, multi-attach |
| st1 | HDD | $0.045 | — | — | Up to 500 MiB/s | Big data, data warehouses |
| sc1 | HDD | $0.015 | — | — | Up to 250 MiB/s | Infrequent access (colder than st1) |
Two things jump out: gp3 is cheaper than gp2 and decouples IOPS from size, and io1/io2 provisioned IOPS cost ~13× more per IOPS than gp3 ($0.065 vs $0.005). Almost all the savings come from those two facts.
The #1 win: switch GP2 → GP3
GP3 replaced GP2 as the default in 2020, yet most accounts still run thousands of GP2 volumes. GP3 is roughly 20% cheaper per GB and gives a flat 3,000 IOPS baseline regardless of volume size.
The performance difference is most dramatic on small volumes. A 100 GiB GP2 volume gets only 300 IOPS (3 per GiB). The same volume on GP3 gets 3,000 IOPS — 10× more — for 20% less money. There is almost no scenario where a small volume should stay on GP2.
On large volumes the win is purely price: a 1 TiB volume drops from ~102/mo(GP2)to 82/mo (GP3), with comparable performance.
Deep dive: Full side-by-side, cost math, and CLI + at-scale migration steps → GP2 vs GP3 on AWS: Save 20% and Get 3,000 IOPS
The catch: there’s functionally no catch. GP2→GP3 is a volume modification, not a rebuild — it can be done with no downtime in most cases. The only reason it doesn’t get done is volume: enterprises have thousands of volumes and nobody owns the task. (That’s the gap automation fills — see below.)
The #2 win: drop io1/io2 for GP3
Provisioned-IOPS storage (io1/io2) is priced for the rare workload that needs guaranteed single-digit-millisecond latency and very high IOPS — large OLTP databases, for example. In practice, the vast majority of io1/io2 volumes were provisioned years ago and never re-evaluated.
GP3 delivers up to 16,000 IOPS — more than enough for nearly all workloads — at a fraction of the cost. The IOPS charge alone tells the story: a volume that needs 10,000 IOPS costs ~650/moinIOPSonio1 * *(0.065 × 10,000) versus **~$35/mo on GP3 (3,000 free + 7,000 × $0.005). That’s a ~95% reduction on the IOPS line, before the cheaper per-GB storage.
AWS’s own guidance is that GP3 can replace io1/io2 for most workloads. You only genuinely need io1/io2 if you require sustained IOPS above 16,000, sub-millisecond latency guarantees, or EBS Multi-Attach.
Deep dive: Performance comparison, a real 4-node Oracle migration, and the pre-flight checklist → GP3 vs io1/io2 on AWS: Cost, IOPS & When to Switch
RDS storage: io1/io2 → GP3
Managed databases inherit the same problem. Many RDS instances were created on io1/io2 storage and left there. Because RDS abstracts the underlying EBS, the waste is invisible until you look — and the savings can be the largest single-line cut in your storage bill, since RDS volumes tend to be large and heavily provisioned.
The pattern is identical to standalone EBS: if the instance doesn’t need sustained IOPS above 16,000 (most don’t), GP3 storage delivers equivalent performance at a fraction of the cost.
Deep dive: How to identify RDS io1/io2 candidates and migrate without downtime → io1/io2 to GP3 on RDS: Cut IOPS Cost Up to 60%
Aurora: Standard vs I/O-Optimized
Aurora Standard charges two things for storage: a per-GB rate and a per-I/O-request rate ($0.20 per million requests). For I/O-heavy databases — e-commerce, analytics, IoT — the I/O charges balloon and quietly become the largest part of the Aurora bill.
Aurora I/O-Optimized flips the model: storage costs 2.25× more per GB ($0.225 vs Standard’s $0.10), but I/O requests are included. Compute pricing is unchanged. The decision is pure math:
- If your I/O charges are less than ~25% of total Aurora spend, stay on Standard.
- If they’re more than ~25%, switch to I/O-Optimized — typical savings are 30–40% for genuinely I/O-heavy workloads.
You can see your I/O share directly in Cost Explorer (filter the Aurora cluster’s costs by the “I/O requests” usage type) or via CloudWatch.
Deep dive: Break-even formula, a worked example, and how to switch → Aurora I/O-Optimized vs Standard: Which Is Cheaper in 2026?
S3: Intelligent-Tiering (and when it’s a trap)
S3 Intelligent-Tiering automatically moves objects between access tiers based on usage: objects not accessed for 30 days drop to a cheaper tier (~40% lower), and after 90 days to a colder tier (~68% lower). Critically, the instant-access tiers have no retrieval fee — performance is unchanged for the tiers that matter day-to-day. AWS reports customers have saved more than $6 billion versus S3 Standard since Intelligent-Tiering launched in 2018.
The only cost is a small monitoring fee: $0.0025 per 1,000 objects per month — applied only to objects larger than 128 KB (smaller objects are exempt and stay in Frequent Access). For most workloads the savings dwarf this fee many times over.
When it’s a trap: Intelligent-Tiering is a bad fit for buckets with a very small number of very large objects, or for data you know is archival (lifecycle rules to Glacier are cheaper). The opt-in Archive tiers also carry multi-hour retrieval, so don’t enable them for data you need fast. But for the common case — application uploads, logs, user content of unknown access pattern — Intelligent-Tiering is almost always a net win.
Deep dive: The five tiers, pricing, and three ways to enable it → S3 Intelligent-Tiering: Does It Actually Save Money?
OpenSearch and managed-service EBS markups
Managed services add a second layer of waste: the EBS storage they attach is often marked up over standard EBS, and the recommended instance sizes are usually oversized. OpenSearch (and Elasticsearch) clusters are the classic example — OpenSearch EBS storage runs roughly 53% above standard GP3 pricing, with similar markups on provisioned IOPS and throughput.
The two levers here are right-sizing (matching instance type/volume to actual CPU and memory usage — typically a 15–20% cut) and architecture choice (Graviton-based instances like m6g vs. their marked-up OpenSearch-tuned equivalents). Both are low-risk if you size against real utilization, not peak assumptions.
Deep dive: Right-sizing steps and the EBS markup table → Cut OpenSearch Costs 15–20%: Right-Size Your Clusters
Decision framework: which storage should I use?
| Your situation | Use this | Typical saving |
|---|---|---|
| Any GP2 volume | GP3 | ~20% + 10× IOPS on small volumes |
| io1/io2 under 16,000 sustained IOPS | GP3 | 60–87% |
| RDS on io1/io2, sub-16K IOPS | GP3 storage | up to 60% on IOPS |
| Aurora, I/O > 25% of spend | Aurora I/O-Optimized | 30–40% |
| S3 objects with unknown/variable access | Intelligent-Tiering | up to 68% |
| Known archival S3 data | Lifecycle → Glacier | 80%+ |
| Oversized OpenSearch/ES clusters | Right-size + Graviton | 15–20% |
| Genuinely need >16K IOPS or Multi-Attach | io2 Block Express | n/a (keep) |
The rule of thumb: default to GP3, switch Aurora to I/O-Optimized if I/O is >25% of spend, tier S3, and reserve io1/io2 only for the rare workload that proves it needs them.
Doing it at scale
The reason these savings persist in almost every account isn’t ignorance — it’s that an enterprise has hundreds of accounts and thousands of volumes, and “migrate every GP2 to GP3” is nobody’s job. The changes themselves are individually trivial and low-risk; the operations problem is finding every candidate and applying the change safely across environments.
That’s exactly what CloudFix does: it continuously scans for these storage opportunities (plus Compute, Network, and Commitment discounts), shows the dollar impact, and applies each change with guardrails — safely, and only charging on realized savings. If you want to see the specific storage savings in your account before touching anything, run a free AWS savings assessment or try the AWS savings calculator.
FAQ
Does migrating GP2 to GP3 cause downtime? No. It’s a volume modification that completes within minutes, typically with no application disruption. You can do a single volume via the AWS CLI or thousands at once with an automation tool.
How do I know if my Aurora database should switch to I/O-Optimized? Check Cost Explorer for your Aurora cluster and compare the “I/O requests” usage cost to total Aurora spend. If I/O is more than ~25% of the total, I/O-Optimized will almost certainly save 30–40%.
Is S3 Intelligent-Tiering worth it for a small bucket? Usually not if the bucket has very few objects — the $0.0025/1,000-objects monitoring fee can outweigh the savings. It’s designed for buckets with many objects and mixed access patterns.
Will dropping io1/io2 hurt my database performance? Only if your workload genuinely sustains more than 16,000 IOPS or needs sub-millisecond latency guarantees. GP3 handles up to 16,000 IOPS, which covers the overwhelming majority of databases. Check actual IOPS utilization in CloudWatch before migrating.
How much can I actually save on AWS storage? It varies, but storage is commonly 20–30% of an AWS bill and the optimizations above typically recover 20–90% of the storage portion depending on what’s currently provisioned. Most accounts find storage is their single cleanest cost win.
Further reading
- GP2 vs GP3 on AWS: Save 20% and Get 3,000 IOPS
- GP3 vs io1/io2 on AWS: Cost, IOPS & When to Switch
- io1/io2 to GP3 on RDS: Cut IOPS Cost Up to 60%
- Aurora I/O-Optimized vs Standard: Which Is Cheaper in 2026?
- S3 Intelligent-Tiering: Does It Actually Save Money?
- Cut OpenSearch Costs 15–20%: Right-Size Your Clusters

