skip to content

A Lambda function backed by an Amazon RDS database starts failing with "too many connections" whenever traffic spikes. What is RDS Proxy, and how does putting it in front of the database fix this?

level: seniorimportance: should knowfreq 45%

answer

  1. one connection per execution environment
  2. the ceiling is set by instance memory
  3. a warm pool in front of the database
  4. many clients, few database sockets
  5. session state breaks the sharing

basics

~20 s

Every concurrent Lambda execution opens its own database connection, so a traffic spike can exhaust the instance's connection limit. RDS Proxy is a managed endpoint inside your VPC that keeps a warm pool of database connections and multiplexes many short-lived client connections onto them.

solid answer

~50 s

Lambda gives each concurrent execution environment its own isolated container, so a thousand concurrent invocations mean up to a thousand database connections opened and torn down independently — and RDS enforces a hard connection ceiling driven by the instance class. **RDS Proxy** is a fully managed proxy that you place between the function and the database, inside the same VPC. Functions connect to the proxy endpoint instead of the database endpoint; the proxy maintains its own warm pool of connections to RDS and multiplexes many client connections over far fewer database ones. That removes both the connection-count ceiling and the per-invocation cost of establishing a connection. It also shortens failover impact, because the proxy holds client connections open while it reconnects to the new writer, and it takes credentials from Secrets Manager so functions can authenticate with IAM instead of embedded passwords. The caveat is **pinning**: session-level state forces the proxy to dedicate a database connection to one client, undoing the multiplexing.

go deeper

for a junior

Know that each concurrent Lambda execution opens its own database connection and that RDS Proxy sits in front of RDS to share a pool of connections between them.

for a middle

Explain the mechanics: the instance-derived connection ceiling, how the proxy multiplexes many client connections onto fewer database ones, and where its credentials come from.

for a senior

Demonstrate that you can diagnose pinning from CloudWatch, weigh the proxy's per-vCPU cost against reserved concurrency as a backstop, and design functions that still handle connection failures during failover.

for a principal

Own the architectural call — whether serverless compute should talk to a connection-oriented database at all, versus fronting it with a long-lived service tier or choosing a request-oriented data interface.

## Why serverless and databases collide AWS Lambda scales by adding *execution environments* — isolated sandboxes, each running one invocation at a time. There is no shared process, so there is no shared connection pool: a library that opens a connection on cold start opens one per environment. Scale to a thousand concurrent invocations and you have asked the database for up to a thousand connections, arriving in a burst. RDS caps concurrent connections, and on the managed engines that cap is derived from the instance's memory through the default parameter group — a small instance class permits far fewer connections than people expect. Worse, each connection is expensive on the server side in memory and setup work, so the failure is not a clean "limit reached" but a slide into degradation: slow connects, timeouts inside the function, retries that open still more connections, and eventually outright rejection. Raising the connection limit in a parameter group trades one failure for another — the database runs out of memory instead. ## What RDS Proxy is RDS Proxy is a fully managed, VPC-resident proxy for RDS and Aurora. You create it, point it at a target database, and it gives you an endpoint that speaks the database's own wire protocol. Clients — Lambda functions, containers, anything — connect to the proxy exactly as they would to the database. ```bash aws rds create-db-proxy \ --db-proxy-name orders-proxy \ --engine-family POSTGRESQL \ --auth '[{"AuthScheme":"SECRETS","SecretArn":"arn:aws:secretsmanager:eu-west-1:123456789012:secret:orders-db","IAMAuth":"REQUIRED"}]' \ --role-arn arn:aws:iam::123456789012:role/rds-proxy-role \ --vpc-subnet-ids subnet-aaa subnet-bbb ``` Behind that endpoint the proxy keeps a pool of established connections to the database and reuses them. A function that connects, runs one query, and returns borrows a warm database connection for the duration of its transaction rather than causing a new one to be built. Thousands of ephemeral client connections can therefore ride on a modest number of database connections. ## The three things it actually buys you **Connection multiplexing.** The headline benefit and the answer to the outage above. Concurrency at the function tier is decoupled from connection count at the database tier. **Faster, gentler failover.** During an RDS failover the writer moves to another host. Without a proxy, every client's socket breaks and every client must detect the failure, re-resolve DNS, and reconnect — the thundering-herd reconnect is often more disruptive than the failover itself. RDS Proxy holds the client connections open, reconnects to the new writer on their behalf, and lets in-flight requests continue, so applications see a pause rather than a storm of errors. **Credential handling.** The proxy pulls database credentials from AWS Secrets Manager using an IAM role you supply, and can require **IAM authentication** from clients. The Lambda function then authenticates with its execution role and never holds a database password, which also means secret rotation is a proxy-side concern rather than a redeploy. ## Pinning: the caveat that separates real experience from a brochure Multiplexing only works while a client connection is stateless between transactions. If a client does something that leaves **session state** on the database connection, the proxy can no longer safely hand that connection to anyone else, so it *pins* the database connection to that one client until the client disconnects. Common causes are temporary tables, session-level `SET` statements, certain prepared-statement and large-object usage, and other engine-specific session features. A pinned workload gets the credential and failover benefits but loses the connection saving — which is exactly the benefit you bought the proxy for. Diagnosing this is a normal part of running a proxy: RDS Proxy emits CloudWatch metrics for pinned connections, and the fix is on the application side, removing the session state or scoping it inside a transaction. ## What RDS Proxy is not It is not a fix for a database that is genuinely out of CPU or I/O — it manages connections, not query cost. It is not a read/write splitter for RDS instances: you point traffic at the proxy's endpoint for the target you configured. It is not free, being billed per vCPU of the target database instance. And it does not remove the need for sensible client-side behaviour — short transactions, prompt release, and idle timeouts still matter. ## Alternatives to name If you cannot use the proxy, the levers are: cap the function's concurrency with reserved concurrency so the database is never asked for more connections than it has; move to an interface that does not hold connections at all, such as the Data API where the engine supports it; or restructure so that a long-lived compute tier, which can hold a conventional pool, fronts the database and the functions call it. Naming reserved concurrency as the crude-but-effective backstop is a good sign in an interview: it makes the blast radius of a traffic spike a queueing problem rather than a database outage.

  • Which CloudWatch signal tells you that RDS Proxy is not actually saving you connections?
    The proxy's pinned-connection metrics. When client connections are being pinned to database connections, multiplexing has stopped and the proxy is little more than a credential broker. Investigate what session state the application leaves behind — temporary tables, session-scoped SET statements, certain prepared-statement patterns — and remove it or confine it within a single transaction.
  • Without RDS Proxy, how would you stop a Lambda traffic spike from exhausting the database's connections?
    Set reserved concurrency on the function so its maximum concurrent executions, and therefore its maximum connections, are bounded by configuration. Excess invocations are throttled or queued rather than reaching the database. It is blunt — you trade function throughput for database stability — but it turns an outage into backpressure, and it takes one setting.
  • Does RDS Proxy remove the need for the function to handle connection errors?
    No. The proxy shortens and softens failover, but clients can still see dropped connections during proxy maintenance, scaling, or a long failover. Functions should still create connections defensively, use short timeouts, and retry idempotent work. Treat the proxy as reducing the frequency and blast radius of connection errors, not as eliminating them.

saying these in an interview costs you the question

  • Lambda executions share one connection pool automatically
  • Just raise max_connections in the parameter group
  • RDS Proxy adds CPU capacity to the database
  • Every workload gets full multiplexing regardless of session state
  • RDS Proxy makes failover invisible with zero client errors

context