serverlessawsdatabasecost-optimization

Pairing functions with a database: the hidden cost of connections

The function is cheap, the database it talks to often is not. Connection limits, proxies, and idle capacity turn a per-request compute model into a per-hour database bill. Here is how to pair them well.

The C3X Team··7 min read

Quick answer

Pairing a scale-to-zero function with an always-on database means the database sets the floor on your bill. A db.t4g.medium RDS instance costs about $0.065 per hour, roughly $47 a month, whether it serves 10 requests or 10 million. RDS Proxy, often required to survive Lambda concurrency, adds $0.015 per vCPU-hour of the underlying instance, about $22 a month for a 2 vCPU instance, a 46 percent uplift. Aurora Serverless v2 at $0.12 per ACU-hour costs about $43 a month at a 0.5 ACU floor. DynamoDB on-demand charges $1.25 per million writes and $0.25 per million reads with no idle cost at all, which is why it pairs most naturally with functions.

Serverless compute has a billing model that matches its usage: nothing runs, nothing is charged. Most databases do not work that way. The moment you put a relational database behind a function, your beautifully elastic cost curve gets a flat floor under it, and for low and medium traffic that floor is usually the largest line on the bill.

The floor each option sets

DatabaseIdle monthly costScales with
DynamoDB on-demand$0 plus $0.25 per GB storageRequests
Aurora Serverless v2 (0.5 ACU floor)~$43.20ACU-hours
RDS db.t4g.micro~$12.00Instance hours
RDS db.t4g.medium~$47.00Instance hours
RDS db.r6g.large~$175.00Instance hours
RDS Proxy (2 vCPU instance)~$21.90Instance vCPU-hours

Storage and I/O sit on top of all the RDS figures: $0.115 per GB-month for gp3 storage, plus backup storage beyond the free allocation. Multi-AZ doubles the instance charge. So a modest Multi-AZ Postgres with a proxy starts around $120 a month before a single query runs.

The connection problem and what it costs

Every concurrent Lambda execution is a separate environment with its own connection. A function scaling to 500 concurrent executions wants 500 connections. A db.t4g.medium Postgres instance defaults to roughly 400 max connections, and each idle connection consumes memory. The usual outcomes are connection exhaustion errors, or a much larger instance bought purely to hold connections rather than to do work.

That second outcome is the expensive one. Upgrading from db.t4g.medium to db.r6g.large to survive connection pressure takes the monthly bill from about $47 to about $175, a $128 increase to serve the same queries. RDS Proxy at $0.015 per vCPU-hour of the instance is usually far cheaper: on a 2 vCPU instance it is about $21.90 a month and multiplexes thousands of client connections onto a small pool.

ApproachMonthly costHandles 500 concurrent functions?
db.t4g.medium alone$47Marginally, with failures under burst
db.t4g.medium + RDS Proxy$69Yes
db.r6g.large alone$175Yes, at 2.5x the price
DynamoDB on-demandUsage onlyYes, no connection concept

When DynamoDB is genuinely cheaper

DynamoDB on-demand charges $1.25 per million write request units and $0.25 per million read request units, with $0.25 per GB-month of storage. An application doing 5 million writes and 20 million reads a month with 20 GB of data costs $6.25 plus $5.00 plus $5.00, about $16.25 total, against $69 for the proxied Postgres setup. Below roughly 40 million writes a month, DynamoDB is usually cheaper on raw numbers.

The caveat is access patterns. If your queries need joins, ad-hoc filtering, or aggregation, modelling them in DynamoDB means secondary indexes that each carry their own write cost, since every write to an indexed attribute writes to the index too. Three global secondary indexes turn one write request unit into four, quadrupling the write bill, as anyindex cost analysis shows. Cheap only holds when the data model fits.

Aurora Serverless v2 as the middle ground

Aurora Serverless v2 bills $0.12 per ACU-hour and scales in 0.5 ACU increments. A floor of 0.5 ACU costs about $43 a month idle, and a workload averaging 2 ACU during 10 business hours and 0.5 ACU otherwise costs roughly $0.12 times (2 times 300 hours plus 0.5 times 420 hours) equals $97 a month. That is more than a fixed small instance at steady load but much less than provisioning for peak, and it keeps full Postgres or MySQL compatibility. It also still needs connection management, though its higher connection limits reduce the pressure.

Non-production environments are where this compounds

The fixed database floor applies per environment, and most teams run three or four. A development, staging, and QA copy of a db.t4g.medium with a proxy is three times $69, or $207 a month, to serve traffic that is effectively zero outside working hours. Functions in those environments cost cents. Two fixes work well: stop non-production RDS instances on a schedule, since a stopped instance charges only for storage and stops automatically restarting after seven days, or use Aurora Serverless v2 with a 0.5 ACU floor so the idle cost is bounded. A third option, sharing one database across non-production environments with separate schemas, cuts the floor to a single instance and is usually acceptable below production.

Practical pairing rules

Put the client creation in module scope so warm invocations reuse connections. Set a low per-function connection pool size, often 1, since each environment handles one request at a time. Use reserved concurrency to cap how many functions can hit the database at once, which is both a reliability and a cost control. For genuinely spiky or low-volume workloads, choose a database with no idle floor. For steady, query-rich workloads, a small fixed instance with a proxy usually beats everything. Price the database alongside the functions against the resource catalog so the floor is a decision rather than a discovery.

FAQ

Why does a database dominate a serverless bill?

Because most databases bill for provisioned capacity by the hour while functions bill only for use. A db.t4g.medium RDS instance costs about $47 a month whether it serves 10 requests or 10 million, plus storage and any Multi-AZ doubling. For low and medium traffic, that fixed floor is usually larger than all the Lambda invocation and duration charges combined.

Is RDS Proxy worth the cost for Lambda?

Usually yes. RDS Proxy costs $0.015 per vCPU-hour of the underlying instance, roughly $21.90 a month for a 2 vCPU instance. The alternative to solving connection exhaustion is a larger instance, and upgrading from db.t4g.medium at about $47 to db.r6g.large at about $175 costs $128 more per month for the same query workload.

How many database connections does Lambda use?

One per concurrent execution environment, since each environment handles a single request at a time and holds its own connection. A function scaling to 500 concurrent executions wants 500 connections, which exceeds what small instances comfortably support. Setting the per-function pool size to 1, reusing clients in module scope, and capping reserved concurrency all help.

Is DynamoDB cheaper than RDS for a serverless app?

Often, below roughly 40 million writes a month. On-demand DynamoDB charges $1.25 per million writes, $0.25 per million reads, and $0.25 per GB-month, so 5 million writes, 20 million reads, and 20 GB costs about $16.25 against $69 for a proxied small Postgres. The caveat is that query patterns needing joins or aggregation may require indexes that multiply write cost.

What does Aurora Serverless v2 cost for a Lambda backend?

It bills $0.12 per ACU-hour with scaling in 0.5 ACU steps. A 0.5 ACU floor costs about $43 a month idle. A workload averaging 2 ACU for 10 business hours daily and 0.5 ACU otherwise costs roughly $97 a month, more than a small fixed instance at steady load but much less than provisioning for peak, while keeping full engine compatibility.

How does C3X help with serverless database pairing?

C3X prices databases, proxies, and functions from Terraform together, so the fixed database floor appears next to the elastic compute in the pull request. That exposes the common case where a scale-to-zero function is paired with an always-on instance and a proxy, making the true monthly minimum of the design visible before it is deployed.

What to do next

See the database floor under your elastic compute. C3X reads your Terraform and prices your resources against a live catalog. Start with the quickstart.

Try C3X on your own Terraform

Free and open source. No API key required. One command to install, one command to estimate.