The database runs out of connections, because every Lambda environment opens its own connections. An execution environment is one running copy of your function. It handles one request at a time and keeps its own connection or pool.
During a spike, hundreds of requests run at the same time. Lambda then creates hundreds of environments, and each one opens connections. You quickly go over PostgreSQL's max_connections limit. Idle environments also keep their connections open until Lambda removes them.
The main fix is RDS Proxy. It sits between Lambda and the database and keeps a pool of database connections. It shares (multiplexes) many client connections over that small pool. It also:
- handles failover more smoothly
- can use IAM authentication
- can use Secrets Manager credentials
Also:
- Create the database client outside the handler, with a pool size of 1, so each environment reuses one connection.
- Set reserved concurrency on the function. This caps how many environments can exist.
- Consider whether another design fits the workload better: a long-running service on ECS with a normal pool, or DynamoDB.
- Each environment opens its own connections, so more concurrent requests mean more connections.
- During spikes, the total goes over PostgreSQL's max_connections.
- RDS Proxy keeps a pool of connections and shares them across many clients.
- Reuse one connection per environment, with a pool size of 1.
- Reserved concurrency caps the number of environments.
Read more