Reduce RDS Costs: A Practical AWS Database Savings Guide
RDS is one of the most common large lines on an AWS bill, and one of the least revisited. Databases get sized for launch day, put on Multi-AZ, given generous storage, and then left alone - because touching the production database feels riskier than paying for it.
This guide shows what an RDS bill is made of, walks through a typical right-sizing case and the checks I run before changing anything, and covers the rest of the bill that right-sizing doesn't touch.
Short answer: right-size the instance from real metrics - CPU, memory, connections, I/O and peak-hour load - validate the smaller class under representative load with a rollback plan, then review storage, IOPS, backups and Multi-AZ separately. Buy Reserved Instances only after the size has settled.
What an RDS bill is made of
- Instance hours - the instance class, billed per hour whether the database is busy or idle.
- Multi-AZ - a standby in a second AZ, which roughly doubles instance and storage cost.
- Storage - per GB-month, with gp3 cheaper per GB than gp2 and io1/io2 the most expensive.
- Provisioned IOPS and throughput - on io1/io2, or gp3 above its included baseline, paid whether used or not.
- Backups - automated backup storage up to the size of your provisioned storage is included; beyond that, and every manual snapshot, is billed.
- Extended Support - engine major versions past end of standard support are automatically enrolled in paid RDS Extended Support, charged per vCPU-hour. It is easy to miss and grows with instance size.
- Data transfer - cross-AZ traffic from applications in other AZs, and cross-region replicas.
Prices vary by engine and region; the RDS for PostgreSQL pricing page has the current rates.
A typical right-sizing case
An illustrative case, representative of what these reviews find: a production PostgreSQL database on db.r6g.xlarge (4 vCPU, 32 GiB) with consistently low CPU utilisation and plenty of memory headroom. After reviewing the metrics below, the proposed change was db.r6g.large (2 vCPU, 16 GiB).
At on-demand list prices that reduces the instance cost by roughly $150-200 a month, depending on region and deployment - and about double that if the instance is Multi-AZ, because the standby shrinks too.
The saving is modest. The process is the point: halving an instance class halves more than CPU, and the checks are what make the change safe.
What I check before downsizing
- CPU at peak, not on average.
CPUUtilizationover at least two weeks including the busiest periods - month-end jobs, campaigns, batch windows. Halving vCPUs doubles peak utilisation; 35% at peak becomes 70%. - Database load against vCPUs. In Performance Insights (now part of CloudWatch Database Insights), average active sessions should stay well under the new vCPU count at peak.
- Memory pressure.
FreeableMemoryandSwapUsage, plus the buffer cache hit ratio. On RDS for PostgreSQL,shared_buffersdefaults to a share of instance memory, so half the memory means half the cache. If the working set no longer fits, reads go to disk and latency rises. - Connections. The default
max_connectionsis derived from instance memory, so it also roughly halves. Compare it with the peak ofDatabaseConnections- this is the check most often skipped, and the one that causes errors after a resize. A connection pooler such as RDS Proxy or PgBouncer removes the problem. - Storage performance.
ReadIOPS,WriteIOPSand throughput against what the instance class supports - smaller classes also have lower EBS bandwidth.
# Peak connections and CPU over two weeks, hourly maximums
for m in DatabaseConnections CPUUtilization; do
aws cloudwatch get-metric-statistics --namespace AWS/RDS --metric-name $m \
--dimensions Name=DBInstanceIdentifier,Value=prod-postgres \
--start-time 2026-10-01T00:00:00Z --end-time 2026-10-15T00:00:00Z \
--period 3600 --statistics Maximum \
--query 'max(Datapoints[].Maximum)'
done
-- Buffer cache hit ratio (aim for ~99% on an OLTP workload)
SELECT round(100.0 * sum(blks_hit) / nullif(sum(blks_hit) + sum(blks_read), 0), 2)
FROM pg_stat_database;
Making the change safely
- Validate under representative peak load first - a staging copy restored from a snapshot, replaying or generating production-like traffic, and watching connections and memory as well as CPU.
- Apply in a maintenance window. On Multi-AZ the standby is modified first and then failed over, which shortens the interruption to roughly a failover; on single-AZ, expect downtime for the resize.
- Have a rollback plan. Resizing back up is the same operation in reverse; decide in advance which metric thresholds trigger it.
- Buy Reserved Instances afterwards, once the new size has run through at least one full business cycle.
The rest of the bill: right-sizing doesn't touch it
Right-sizing the instance doesn't automatically optimise the rest of the RDS bill. Review each of these separately:
- Storage type. gp2 to gp3 is cheaper per GB and includes baseline IOPS and throughput; io1 volumes provisioned for a performance target years ago are often far above what the workload uses.
- Provisioned IOPS. Compare provisioned IOPS with actual
ReadIOPS + WriteIOPSat peak. - Backup retention and manual snapshots. Retention set to the maximum by default, and manual snapshots from migrations that are years old, keep billing.
- Multi-AZ per environment. Essential in production; rarely needed in dev, test or most staging environments.
- Non-production schedules. Stopped instances stop paying for compute but not storage - and RDS automatically restarts a stopped instance after seven days, so schedules need to re-stop it.
- Engine version. Upgrading off an engine version in Extended Support removes that charge entirely.
- Graviton. If you're still on Intel classes, moving to Graviton (r6g, r7g, m7g) is usually cheaper for the same or better performance.
- Read replicas. Each one is a full instance. Remove replicas added for a migration or a one-off report and never decommissioned.
Mistakes to avoid
- Downsizing on average CPU. Peak load, memory and connections decide whether the smaller class works.
- Forgetting that memory drives connection limits. The resize succeeds, then the application hits
too many connectionsat the next peak. - Buying Reserved Instances before right-sizing. You lock in the oversized class for one or three years.
- Treating the instance as the whole bill. Storage, IOPS, backups, Multi-AZ and Extended Support are separate levers.
FAQ
How do I know if my RDS instance is oversized?
Look at peak CPU, database load against vCPUs, freeable memory and cache hit ratio, and peak connections over at least two weeks. If all of them would still have comfortable headroom at half the capacity, the instance is a candidate - then validate under load before changing it.
Does resizing an RDS instance cause downtime?
Yes for single-AZ instances. With Multi-AZ, RDS modifies the standby and fails over, so the interruption is close to a normal failover. Schedule it in a maintenance window either way.
Are Reserved Instances worth it for RDS?
For production databases that run continuously at a settled size, yes. Not before right-sizing, and not for non-production instances that are stopped part of the time.
Does stopping an RDS instance stop all charges?
No. Compute stops, but storage, provisioned IOPS and backups keep billing - and RDS starts the instance again automatically after seven days.
Want a second opinion on your database bill?
RDS review is part of every AWS cost optimization engagement I run. For where databases fit in the overall order of work, see the AWS cost optimization guide; the EC2 rightsizing guide applies the same method to compute.
Tags:
Need help with this?
I offer hands-on consulting on exactly this — aws cost optimization consulting .