Back to Blog
AWSAuroraRDSreduce_costs

When a serverless database saves money and when it burns it

Aurora Serverless v2 ACU economics, the utilization threshold where it flips more expensive than a reserved r-class, plus RDS Proxy and stop/start for real savings.

JohannaMarch 8, 20265 min read

"Serverless" reads as "cheaper" to a lot of people, and for databases that intuition is right about half the time. Aurora Serverless v2 is genuinely excellent for workloads that are spiky, intermittent, or idle much of the day. It is genuinely more expensive than a right-sized provisioned instance for workloads that run hot and steady. The whole decision comes down to a utilization threshold you can calculate, plus a couple of adjacent tools — RDS Proxy and instance stop/start — that often save more than the serverless-vs-provisioned choice itself. Here is where the lines actually cross.

Prices are us-east-1, on-demand unless noted, and will vary by region and over time. The ratios are what matter.

How Aurora Serverless v2 bills

Serverless v2 measures capacity in Aurora Capacity Units (ACUs). One ACU is approximately 2GB of memory with proportional CPU and networking, and you are billed per ACU per second — roughly $0.12 per ACU-hour. Capacity scales in fine-grained 0.5-ACU steps in response to load, up to 128 ACU (256GB).

Two details govern the economics:

  • The floor. For a long time the minimum was 0.5 ACU, meaning an "idle" serverless instance still cost ~$0.06/hour, about $43/month per instance that never sleeps. AWS later added the ability to scale to 0 ACU (auto-pause) after a configurable idle period — which makes dev and rarely-used databases genuinely cheap, at the cost of a cold-start when traffic returns. Whether 0-ACU pause is right depends on your latency tolerance for the first request after idle.
  • Scale-up latency. v2 scales quickly — seconds, not the minutes v1 took — but it is not instantaneous, and it steps up roughly by doubling. A load spike that arrives faster than the scaler reacts will see latency until capacity catches up. For bursty-but-tolerant workloads this is invisible; for a hard, sudden thundering-herd it is a real consideration, and you may need to set a higher minimum ACU to pre-warm.

The threshold where serverless flips

Do the arithmetic against a provisioned instance. A db.r6g.large is 2 vCPU and 16GB — comparable in memory to about 8 ACU — and runs around $0.29/hour on-demand, roughly $210/month if it runs 24/7. A reserved instance (1- or 3-year) knocks a large chunk off that, often 30–60%.

Now the serverless side. At $0.12/ACU-hour, 8 ACU held continuously is ~$0.96/hour — about $700/month, more than three times the on-demand provisioned instance and far more than the reserved one. But serverless only bills for capacity you actually consume, second by second. If that same workload averages, say, 2 ACU over the day with brief peaks to 8, you pay for the 2-ACU average: ~$0.24/hour, ~$175/month — now cheaper than the always-on r6g.large.

The break-even, stated as a rule:

  • Serverless wins when average utilization is low — the workload is idle overnight and on weekends, or has short bursts separated by long quiet stretches, so your average ACU sits well below the capacity a provisioned instance would keep running 24/7. Below roughly 30–40% sustained utilization of the equivalent instance, serverless usually comes out ahead, and dramatically so for dev/test databases that can pause to 0.
  • Provisioned wins when utilization is high and steady. Once a workload keeps an instance meaningfully busy around the clock, you are paying serverless's per-second premium for capacity you'd hold anyway. A right-sized r-class instance plus a 1- or 3-year reservation is the cheapest way to run a database that is always working, often less than half the serverless cost at the same effective capacity.

The trap is provisioning serverless with a high minimum ACU "for safety" and then running steadily near it. That is the worst of both models: you pay the serverless rate and forfeit the reservation discount you'd get by committing to a provisioned instance of the same size. If you find your serverless floor and ceiling converging on a steady number, that number is telling you to move to a reserved provisioned instance.

RDS Proxy: the fix for connection storms

This is a different lever, and for Lambda-heavy architectures it is frequently the more important one. Every concurrent Lambda invocation that opens its own database connection multiplies fast, and relational engines cap connections (max_connections scales with instance memory). A traffic spike drives Lambda concurrency into the hundreds or thousands, each grabbing a connection, and the database hits its limit and starts refusing new connections — connection exhaustion, right when you're busiest.

RDS Proxy sits between the application and the database and pools connections, multiplexing many client connections onto a small set of real database connections. It absorbs connection storms, and it also speeds failover. It bills at about $0.015 per vCPU-hour of the underlying database instance, per proxy — for a 2-vCPU instance that's ~$0.03/hour, roughly $22/month (with minimum-vCPU billing that raises the floor for very small instances). That is cheap insurance against an outage class that is otherwise hard to engineer around, and far cheaper than over-sizing the database purely to raise its connection ceiling.

Stop/start for everything non-prod

The most underused RDS cost lever has nothing to do with serverless. You can stop a provisioned RDS or Aurora instance, and while it's stopped you pay only for storage and backups — not instance-hours. The catch: a stopped instance auto-starts after 7 days, so you can't just leave it off forever, but you can absolutely stop it every evening and weekend.

For non-prod fleets this is enormous. A dev/test/staging environment that only needs to run during working hours — say 50 hours a week out of 168 — spends about 70% of its life idle. Stop it on a schedule (an EventBridge rule or the native scheduler) and you cut those instance-hours by roughly that 70% for free. No re-architecture, no serverless migration, just turning it off when nobody is using it. For non-prod databases that don't need to survive a 7-day gap, Aurora Serverless v2's scale-to-0 achieves the same idle savings automatically without the auto-restart ceiling.

Deciding, quickly

  1. Non-prod? Schedule stop/start, or use Serverless v2 with a 0-ACU floor. Idle time should cost near zero.
  2. Spiky or intermittent prod, low average utilization? Serverless v2 — you pay for the average, not the peak.
  3. Steady, high-utilization prod? Right-sized r-class instance plus a reservation. Don't pay serverless rates to hold capacity you'd hold anyway.
  4. Lambda talking to a relational database? Put RDS Proxy in front regardless of the above — the per-vCPU fee is trivial next to a connection-exhaustion outage.

Serverless is a pricing model, not a discount. It saves money when your workload is genuinely bursty and wastes it when your workload is genuinely steady. Measure the average utilization, find where it sits against that 30–40% line, and the rest follows.