RDS and Aurora Cost Optimization: Seven Places to Look

RDS and Aurora cost optimization: Aurora I/O-Optimized break-even, Serverless v2 scale to zero, gp3 vs io1, Extended Support fees, idle replicas.

On 1 August 2026, every RDS for MySQL 8.0 database that hadn’t been upgraded picked up a new line on its bill: $0.10 per vCPU per hour for Extended Support. Nothing broke and no alarm fired. The database kept running exactly as before, just more expensively, and plenty of teams will only notice when the September invoice gets a second look.

That’s the pattern with managed databases. The instance is the part everyone sees, but a lot of the money sits in settings chosen once and never revisited: the Aurora storage configuration, a Serverless v2 floor, provisioned IOPS, a standby in staging, a replica from last year’s reporting project. Below are the seven we check first, with us-east-1 on-demand list prices at the time of writing and the commands to find each one.

Start with the bill, not the console

Cost Explorer groups RDS and Aurora under one service, and the usage types tell you which of the sections below matter for you. This pulls last month’s spend by usage type. Each Cost Explorer API call costs $0.01.

# Read-only: last full month of RDS and Aurora spend by usage type
# (the first form is GNU date on Linux, the fallback is BSD date on macOS)
START=$(date -u -d "$(date -u +%Y-%m-01) -1 month" +%F 2>/dev/null || date -u -v1d -v-1m +%F)
END=$(date -u +%Y-%m-01)
aws ce get-cost-and-usage \
  --time-period Start=$START,End=$END \
  --granularity MONTHLY --metrics UnblendedCost \
  --filter '{"Dimensions":{"Key":"SERVICE","Values":["Amazon Relational Database Service"]}}' \
  --group-by Type=DIMENSION,Key=USAGE_TYPE \
  --query 'ResultsByTime[0].Groups[].[Keys[0],Metrics.UnblendedCost.Amount]' \
  --output text | sort -k2 -rn | head -25

Look for StorageIOUsage (Aurora I/O), ExtendedSupport, BackupUsage, PIOPS and Multi-AZUsage. Outside us-east-1 the names carry a region prefix such as USE2-.

1. Extended Support on old major versions

When a major version passes the end of standard support, RDS enrols the database in Extended Support automatically and starts charging per vCPU-hour. For RDS for MySQL, RDS for PostgreSQL and Aurora the rate is $0.10 per vCPU-hour in years one and two, then $0.20 from year three. Aurora Serverless v2 pays $0.085 per ACU-hour, then $0.17. Multi-AZ standbys are charged too.

Engine and version Charges started Year 3 rate starts
RDS for MySQL 5.7 1 March 2024 1 March 2026
RDS for MySQL 8.0 1 August 2026 1 August 2028
RDS and Aurora PostgreSQL 12 1 March 2025 1 March 2027
RDS and Aurora PostgreSQL 13 1 March 2026 1 March 2028
Aurora MySQL version 2 1 December 2024 1 December 2026
RDS and Aurora PostgreSQL 14 1 March 2027 1 March 2029

Here’s what that means for a db.r7g.2xlarge (8 vCPUs) running MySQL 8.0 in Multi-AZ. The instance itself is $1.913 an hour, about $1,396 a month. Extended Support adds 8 vCPUs × $0.10 × 2 instances, or $1.60 an hour, which is $1,168 a month. That’s 84% on top of the instance, and it doubles in year three.

Aurora MySQL version 2 is the urgent one: its rate goes from $0.10 to $0.20 per vCPU-hour on 1 December 2026. PostgreSQL 14 is next, with charges from 1 March 2027.

# Read-only: engine versions and Extended Support enrolment
aws rds describe-db-clusters \
  --query 'DBClusters[].[DBClusterIdentifier,Engine,EngineVersion,EngineLifecycleSupport]' \
  --output table
aws rds describe-db-instances \
  --query 'DBInstances[?!DBClusterIdentifier].[DBInstanceIdentifier,Engine,EngineVersion,EngineLifecycleSupport]' \
  --output table

Enrolment alone doesn’t mean you’re paying; charges begin only once the version is past its date. The fix is a major version upgrade, and blue/green deployments keep the cut-over short. You can also create new databases with --engine-lifecycle-support open-source-rds-extended-support-disabled so a forgotten version can’t quietly start billing. Be careful setting that on an existing database that’s already past its date, though: it triggers an automatic major version upgrade.

Paying for a few months isn’t always wrong. If an upgrade needs application changes you can’t test before the date, Extended Support is the price of doing it properly. Just put an end date on it.

2. Aurora Standard vs I/O-Optimized

Aurora has two storage configurations. Standard charges $0.10 per GB-month plus $0.20 per million I/O requests. I/O-Optimized charges nothing for I/O but raises storage to $0.225 per GB-month and instance prices by about 30% (db.r7g.xlarge goes from $0.553 to $0.719 an hour). AWS’s guidance is that I/O-Optimized wins once I/O is 25% or more of your Aurora spend.

Treat 25% as a starting point and do the sum for your own cluster. Take two db.r7g.xlarge instances, 1,000 GB of storage and 3 billion I/O requests a month:

Standard I/O-Optimized
Instances (2 × 730 hours) $807.38 $1,049.74
Storage (1,000 GB) $100.00 $225.00
I/O (3,000 million requests) $600.00 $0
Monthly total $1,507.38 $1,274.74

I/O is 40% of the Standard bill, and switching saves about $233 a month. The break-even for this cluster is roughly 1.84 billion requests a month, at which point I/O is about 29% of spend, not 25%. Clusters with a lot of storage relative to instance size break even later. Small, busy clusters break even sooner.

You can move from Standard to I/O-Optimized once every 30 days and back at any time. On instances without local NVMe storage there’s no downtime. AWS Compute Optimizer also recommends this switch for Aurora Standard clusters, but it only suggests the one direction, so I/O-Optimized clusters doing very little I/O are yours to find. Check StorageType in describe-db-clusters: aurora is Standard and aurora-iopt1 is I/O-Optimized.

3. Aurora Serverless v2 floors and ceilings

Serverless v2 bills $0.12 per ACU-hour on Standard and $0.16 on I/O-Optimized. An ACU is roughly 2 GiB of memory with matching compute. The cost risk is the minimum. A floor of 8 ACUs costs $700.80 a month per instance even when nothing is connected, and floors that high are often set once to survive a load test, then left in place.

Serverless v2 can scale to zero now. With a minimum of 0 ACUs, an instance pauses after a period you set (300 seconds to one day) and stops billing for compute, though storage still bills. It needs Aurora PostgreSQL 13.15, 14.12, 15.7, 16.3 or later, or Aurora MySQL 3.08.0 or later. Resuming takes about 15 seconds, and 30 seconds or more after a day paused, so it suits dev, test and preview environments, not anything user-facing. An open connection (an idle pool counts), RDS Proxy, logical or binlog replication, zero-ETL and global databases all block the pause.

# Read-only: Serverless v2 scaling settings per cluster
aws rds describe-db-clusters \
  --query 'DBClusters[?ServerlessV2ScalingConfiguration].[DBClusterIdentifier,EngineVersion,ServerlessV2ScalingConfiguration.MinCapacity,ServerlessV2ScalingConfiguration.MaxCapacity,ServerlessV2ScalingConfiguration.SecondsUntilAutoPause]' \
  --output table

Compare each floor with the instance’s ServerlessDatabaseCapacity metric. If capacity sits on the floor for weeks, the floor is setting the bill. Readers in promotion tiers 0 and 1 scale with the writer, so a standby reader costs as much as the writer during busy hours. And serverless isn’t automatically cheaper: a provisioned db.r7g.large on Aurora is $0.276 an hour, the price of 2.3 ACUs. A database that averages more than that around the clock, and fits in 16 GiB at peak, costs less provisioned.

4. RDS storage: provisioned IOPS nobody uses

On RDS for MySQL, PostgreSQL and MariaDB, gp3 is $0.115 per GB-month. Volumes of 400 GiB or more get 12,000 IOPS and 500 MiB/s included; smaller ones get 3,000 IOPS and 125 MiB/s. Extra IOPS cost $0.02 per IOPS-month. io1 and io2 are $0.125 per GB-month plus $0.10 for every provisioned IOPS-month.

That per-IOPS charge is where the money goes. A 1,000 GB io1 volume provisioned at 10,000 IOPS costs $1,125 a month in Single-AZ, $1,000 of it for IOPS. The same size on gp3 is $115 and includes 12,000 IOPS. Multi-AZ doubles both figures. Check the peak of ReadIOPS plus WriteIOPS over a few weeks before choosing a number.

Keep io2 where it earns its price: busy OLTP databases that need consistently low latency or more IOPS than gp3’s 64,000 ceiling. A storage-type change triggers an optimisation phase that can take hours, and you can’t modify storage again for six hours or until it finishes.

One quirk: gp2 and gp3 cost the same per GB on RDS, unlike on EBS. The gain from gp3 is that IOPS no longer come from size, so a gp2 volume grown to 2 TB just to get 6,000 IOPS is mostly paying for empty disk. RDS can’t shrink allocated storage in place, but blue/green deployments can for RDS for MySQL 5.7+, PostgreSQL 12+ and MariaDB 10.4+.

5. Multi-AZ where nobody needs failover

Multi-AZ on a single-instance deployment doubles the instance and the storage. A db.r7g.large running PostgreSQL is $0.239 an hour in Single-AZ and $0.478 in Multi-AZ, and 500 GB of gp3 goes from $57.50 to $115 a month. Turning it off in staging saves about $232 a month on that one database.

# Changes availability, not data: turns off Multi-AZ on a non-production instance.
# Agree it with the owner first; --apply-immediately skips the maintenance window.
aws rds modify-db-instance --db-instance-identifier staging-orders \
  --no-multi-az --apply-immediately

Keep it where you rehearse failovers or measure write latency. Databases only used in working hours can also be stopped for up to seven days at a time, after which RDS starts them again. Storage and backups bill while they’re stopped.

6. Backups beyond the free allowance

RDS gives you backup storage free up to the total provisioned storage of your databases in the region. Beyond that it’s $0.095 per GB-month for RDS engines and $0.021 for Aurora. The usual causes of going over are 35-day retention on databases with heavy write churn, cross-region automated backup replication that someone turned on for an audit, and manual snapshots that outlive the database. We covered those leftover snapshots in idle and orphaned AWS resources. For the rest, agree a retention period per environment; seven days suits most test databases.

7. Replicas nobody reads, and instances sized for 2023

A read replica costs as much as any instance of its class, and replicas made for a reporting job or a migration tend to outlive it. Check peak connections per day over two weeks:

# Read-only: daily peak connections for one replica or Aurora reader, last 14 days
START=$(date -u -d '-14 days' +%FT%TZ 2>/dev/null || date -u -v-14d +%FT%TZ)
END=$(date -u +%FT%TZ)
aws cloudwatch get-metric-statistics --namespace AWS/RDS \
  --metric-name DatabaseConnections \
  --dimensions Name=DBInstanceIdentifier,Value=reporting-replica-1 \
  --start-time $START --end-time $END --period 86400 --statistics Maximum \
  --query 'sort_by(Datapoints,&Timestamp)[].[Timestamp,Maximum]' --output text

A steady one or two is usually a monitoring agent. Search your config for the replica’s endpoint before you trust that, and remember that an Aurora reader is also the failover target. Removing the only reader means a failover has to build a new instance, which takes far longer. Cross-region replicas are often someone’s disaster recovery plan, so ask first.

# DESTRUCTIVE: deletes an RDS read replica. Run the connection check above
# first and confirm with the owner. The source keeps all of the data.
REPLICA=reporting-replica-1
read -r -p "Type $REPLICA to delete it: " CONFIRM
[ "$CONFIRM" = "$REPLICA" ] && aws rds delete-db-instance \
  --db-instance-identifier "$REPLICA" --skip-final-snapshot

For rightsizing, CPU alone misleads, because databases use spare memory as cache. Read CPUUtilization, FreeableMemory and DBLoad together; a DBLoad well below the vCPU count means headroom. After a downsize, watch read IOPS. If they climb, the working set no longer fits in memory. Compute Optimizer gives instance and storage recommendations for RDS for MySQL and PostgreSQL and both Aurora engines, though not for Serverless v2. Performance Insights’ own dashboard was retired on 30 June 2026 in favour of CloudWatch Database Insights. Standard mode keeps seven days free. Advanced mode bills $0.0125 per vCPU-hour, about $73 a month for an 8-vCPU instance, so check which mode your test databases run in.

Moving to Graviton is the other instance lever; our rightsizing and Graviton guide covers it for RDS too. Commitments come last, once sizes have settled: see Reserved Instances vs Savings Plans and the Database Savings Plans section of AWS billing discounts you probably missed.

FAQ

Is Aurora I/O-Optimized worth it?

When I/O is roughly a quarter to a third of the cluster’s Aurora spend. Work it out per cluster from last month’s bill; storage-heavy clusters need more I/O to break even.

Can Aurora Serverless v2 scale to zero?

Yes, on Aurora PostgreSQL 13.15, 14.12, 15.7, 16.3 or later and Aurora MySQL 3.08.0 or later. Set the minimum to 0 ACUs. The instance pauses when it has no connections and takes about 15 seconds to resume.

How do I stop paying RDS Extended Support?

Upgrade to a major version still in standard support. Charges stop the day the upgrade completes. Deleting the database also stops them.

Is gp3 cheaper than io1 on RDS?

Usually by a wide margin: gp3 includes 3,000 or 12,000 IOPS, while io1 bills $0.10 a month for every IOPS you provision.

Does a stopped RDS instance cost anything?

Yes. Instance hours stop, but storage, provisioned IOPS and backups keep billing, and RDS restarts the instance after seven days.

Two dates for your calendar

Run the two describe commands from section 1 this week and list every database on Aurora MySQL version 2 or PostgreSQL 14. The first doubles its Extended Support rate on 1 December 2026; the second starts paying on 1 March 2027. Book the upgrades now, while there’s time to test them. If you want the storage and capacity checks done on every scan, Kostrix compares each Aurora cluster’s storage configuration with its measured I/O and flags Serverless v2 floors a cluster never rises above.