The Aurora cluster looked cheap when it launched — one writer, modest storage, nothing exotic. Six months later the RDS line on the bill has climbed and nobody changed the instance class. Nobody resized storage either; Aurora does that automatically. The usual suspects — an oversized instance, a forgotten Multi-AZ standby — don't explain it, because Aurora doesn't work that way. What actually happened is somewhere else in the cluster: a reader instance nobody removed, a Serverless v2 database that never scales below its floor, or a Global Database secondary Region quietly billing its own storage and I/O. None of these show up if you're only looking at the writer's instance class.
Why does an Aurora bill grow without anyone resizing anything?
Aurora bills four things independently, and three of them have nothing to do with the instance class you picked at launch:
- Instances — every reader and writer in the cluster is its own full instance-hour, billed at the same rate regardless of how much it's actually queried.
- Storage and I/O — the cluster volume grows and shrinks automatically with your data, and Aurora Standard meters every read/write request to it separately at $0.20 per million I/Os.
- Serverless capacity — if any instance in the cluster runs on Aurora Serverless v2, it bills by the Aurora Capacity Unit (ACU) per second, with a floor that most clusters never drop below.
- Cross-Region replication — a Global Database secondary Region is a second cluster with its own storage and its own share of replicated I/O.
How does Aurora's storage model actually work, and where does the I/O charge come from? covers the storage-versus-I/O mechanics in depth — the $0.10 per GB-month Standard rate, the $0.20-per-million-I/Os meter, and when I/O-Optimized's $0.225 per GB-month with zero I/O charges is the better deal. This post is about the three things that inflate an Aurora bill independent of that model: instances you forgot were running, a Serverless floor nobody checked, and replication most teams don't realize is billed per-Region.
Is a reader instance the reason the bill jumped?
Aurora's redundancy story is that the storage layer is already replicated three ways, so you don't need a Multi-AZ standby the way RDS does. That's true for storage. It is not true for instances. Every Aurora reader — added for read scaling, for a blue-green deployment, for a load test that finished months ago — bills as a complete separate instance-hour at the same rate as the writer.
A db.r6i.large writer on Aurora Standard runs about $0.29 per hour (roughly $212/month at
730 hours). Add one reader of the same class for read scaling and the cluster's instance line
doesn't grow by a fraction — it doubles, because the reader is a second full instance, not a
discounted standby. On Aurora I/O-Optimized the same class runs about $0.377/hour per instance.
This is the single most common way a cluster's instance cost creeps: someone adds a reader for a specific, temporary reason — a migration, a reporting job, a spike — and the reader outlives the reason. Unlike storage, nothing about Aurora shrinks a reader count automatically. It sits there billing until someone notices and removes it.
Is the bill actually Serverless v2 never idling down?
If any instance in the cluster is Aurora Serverless v2, check its capacity range before looking anywhere else. Serverless v2 bills $0.12 per ACU-hour on Standard ($0.156 on I/O-Optimized), scaling in fractional increments — but AWS's own guidance calls 0.5 ACU "tempting to always choose" as the minimum, because it's the smallest value that keeps the instance active without fully pausing it. A cluster left at that default minimum bills 24 hours a day, 7 days a week, whether or not a single query ever runs against it.
The arithmetic on that floor is small per hour and large per year:
| Minimum ACU | Rate/hour | Monthly cost (730 hrs), doing nothing |
|---|---|---|
| 0.5 ACU | $0.06 | ~$43.80 |
| 1 ACU | $0.12 | ~$87.60 |
A dev database, a staging environment, a low-traffic side project left at a 1 ACU minimum instead of 0.5 pays roughly double for capacity it never uses outside business hours. AWS added a genuine scale-to-zero option — a minimum capacity of 0 ACUs with automatic pause and resume — that removes this floor entirely for workloads that can tolerate a cold-start delay on the next connection. Most teams never set it, because 0.5 was the default they accepted when the cluster was created and nobody has revisited it since.
Pull the current capacity range for a cluster's instances:
aws rds describe-db-instances \
--query 'DBInstances[?Engine==`aurora-postgresql` || Engine==`aurora-mysql`].[DBInstanceIdentifier,DBInstanceClass,ServerlessV2ScalingConfiguration]' \
--output table \
--region us-east-1
Anything showing a Serverless instance class (db.serverless) with MinCapacity at 0.5 or higher on a database that's genuinely idle outside a known window is worth checking against its ServerlessDatabaseCapacity CloudWatch metric before you touch the setting.
Dropping the minimum ACU on a cluster with real traffic can hurt latency — a lower floor means a
colder starting point every time load increases, and Aurora scales up over seconds, not
instantly. Check ServerlessDatabaseCapacity over at least 14 days before changing the minimum on
anything other than a database you already know sits idle for long stretches.
Is Global Database the reason a second Region shows up on the bill?
Aurora Global Database replicates a cluster to one or more secondary Regions for disaster recovery or low-latency reads, and it's billed as what it actually is: a second full cluster. The secondary Region's storage bills at the same per-GB rate as the primary — $0.10 per GB-month on Standard, $0.225 on I/O-Optimized — as its own line, not a discount on the primary's. Replicated write I/O between the primary and each secondary Region bills at the same $0.20-per-million-I/Os rate on Standard. On top of both, data transferred between Regions for the replication itself bills at standard AWS inter-region transfer rates, around $0.02 per GB — the one part of Aurora replication that has nothing to do with Aurora's own pricing model at all.
None of this is hidden, exactly — it's on the pricing page — but it's easy to reason about a Global Database as "one cluster with a DR copy" rather than as two clusters and a data-transfer bill. A 500 GB primary with a single secondary Region roughly doubles the storage line on its own, before any replicated I/O or transfer charges are added.
These are standard us-east-1/cross-Region on-demand rates at the time of writing, rounded for
clarity. Rates vary by Region pair and AWS changes them — check the
Aurora pricing page before you build a DR business
case around any of these numbers.
How do I see which of these is actually driving my bill?
Cost Explorer, grouped by Usage Type with the service filtered to RDS, splits Aurora's meters apart by name: InstanceUsage per instance (readers show up as their own line items, not folded into the writer), Aurora:StorageUsage for storage, Aurora:StorageIOUsage for I/O requests, and USE2-Aurora:StorageUsage (or the equivalent for whichever secondary Region you're replicating to) for a Global Database secondary. If a Region code you didn't expect shows up in that breakdown, that's the Global Database secondary announcing itself.
For the instance count specifically, list every instance in every cluster before assuming the writer is the only thing running:
aws rds describe-db-clusters \
--query 'DBClusters[].[DBClusterIdentifier,DBClusterMembers[].DBInstanceIdentifier]' \
--output table \
--region us-east-1
A cluster with more entries in that second column than you remember provisioning is exactly the reader-instance pattern from above.
What else should I check before I decide anything's wrong?
If storage or I/O turns out to be the meter that's actually growing — rather than instances, Serverless capacity, or replication — that's the deeper mechanics covered in Aurora vs RDS: which one costs less to run?, including the 25%-of-spend rule of thumb for when switching to I/O-Optimized pays for itself. And if the comparison that's actually on the table is provisioned RDS rather than another Aurora cluster, how RDS pricing actually breaks down has the equivalent meters for that side.
Aurora instance and replication charges are also rarely the only thing worth a look once you're checking Cost Explorer line by line — the full list of what else quietly adds up on an AWS bill covers the rest of an account in roughly the order it pays off to check it.
How do I catch this drift before it's six months old?
Checking one cluster's instance count, Serverless floor, and Region list by hand takes a few minutes. Doing that for every Aurora cluster in every Region, and catching it again the next time someone adds a reader for a migration and forgets to remove it, is the part that stops happening after the first pass. Parsivex checks every Region for over-provisioned and idle RDS and Aurora instances against real 14-day metrics, and then keeps watching, so a reader or a Serverless floor that drifted back into waste gets flagged instead of running quietly for another six months. For what these findings mean once they show up in your report, see Over-provisioned RDS instance and Idle RDS instance.