What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Serverless functions can exhaust PostgreSQL connections because each running function instance may create its own client pool. As instances scale up, those pools multiply: a pool of 10 connections on each of many warm instances can demand far more database sessions than expected. Reuse one client per instance, keep its pool appropriately small, and use a compatible pooler or proxy when connection churn or concurrency calls for one.
How serverless scaling multiplies database connections
A connection pool belongs to the application process or function instance that created it; it is not automatically shared across every instance of a serverless service. When traffic rises, the platform may run more instances, each with its own pool. The potential PostgreSQL connection demand is therefore roughly:
As an Amazon Associate I earn from qualifying purchases.
concurrently active instances × maximum connections per instance
This is a planning model, not a universal sizing formula. Leave room for administrative access and other database clients. On Supabase, platform services such as Auth, Storage, PostgREST, and the health checker also use the database’s connection budget. Supabase documents its connection-pooling guidance and platform connection use.
#1 Best Overall
The multiplication can be easy to miss when a pool size was chosen for a single, long-lived application server. Supabase notes that Postgres.js defaults to 10 connections per warm function instance and warns that only a few dozen instances can exhaust a pool. That figure is specific to the documented Postgres.js/Supabase context, not a general PostgreSQL limit. See Supabase’s current connection guidance.
Find where the connections are coming from
- Estimate concurrent instances. Use realistic peak or burst concurrency, not just the number of deployed functions. Multiply that by the maximum pool size configured for each instance, then account for other database clients and reserve capacity for administration.
- Check client construction. Look for code that creates a new database client or pool inside the request handler. Where the runtime reuses warm instances, initialize the client once at module scope so later invocations can reuse it. Supabase explicitly recommends this pattern for its serverless functions; adapt it to the lifecycle and driver used by your platform. Supabase’s example and explanation.
- Inspect the driver’s pool maximum. Find the actual maximum in the driver or ORM configuration. Multiply it by plausible instance concurrency. Do not assume that a default—or another provider’s example—is safe for your workload.
- Check the database endpoint and pooling mode. Confirm whether the application connects directly, through a provider pooler, or through a managed proxy. Verify compatibility with your driver’s prepared statements and any code that relies on session state.
- Measure during realistic concurrency. Track database connections, application pool wait time, connection errors, request latency, and any queueing or rejected requests at a proxy. The acceptable levels depend on the database and application; the documented provider guidance does not establish universal alert thresholds.
Reduce connections before adding infrastructure
Reuse one client per warm instance
Keep client creation outside the per-request handler when the runtime allows the instance to serve multiple invocations. Creating a pool for every invocation can cause needless connection churn and may leave connections open depending on runtime cleanup. A module-scope client is reused only within that instance; it does not become a global pool shared across all instances.
Rank #2
Set a small, deliberate local pool
Choose a per-instance maximum based on measured same-instance concurrency and the database’s total session budget. Supabase’s Postgres.js serverless example uses max: 1; its guidance says to raise that only when evidence shows invocations within one instance are queuing. That is a provider- and client-specific starting point, not a rule for every driver, ORM, or workload. Supabase explains the example and its limits.
Recommended Free Tools
A small pool limits how many sessions one instance can open, but it does not eliminate multiplication across instances. If requests queue behind the local pool, first determine whether that is acceptable and whether the total database capacity supports increasing it. Raising the maximum without recalculating across instances can make exhaustion worse.
Rank #3
Choose direct connections, a transaction pooler, or a proxy
| Approach | Best fit | Main trade-off |
|---|---|---|
| Direct connections with a small per-instance pool | Low or controlled concurrency and a simple topology | Each instance still consumes backend database sessions, so total concurrency must fit within capacity. |
| Provider transaction pooler, such as Supabase transaction mode | Many short, independent serverless or edge transactions | Session-dependent behavior may not persist between transactions, and prepared-statement support depends on the pooler and driver configuration. |
| Managed database proxy, such as AWS RDS Proxy | AWS Lambda workloads connected to RDS that experience frequent connection opens and closes or surges | Adds a proxy layer and provider-specific configuration; when capacity is unavailable, requests may wait, be throttled, or be rejected. |
| Persistent application service with a bounded pool | Workloads that need long-lived sessions or more predictable pooling | Requires operating persistent compute. It avoids per-instance serverless churn only if its own pool is bounded and managed. |
Transaction pooling and session behavior
In transaction mode, a client connection is assigned to a database connection for a transaction, then the database connection can return to the shared pool. Code that expects a particular database session to remain attached across transactions may not work as expected. Supabase says prepared statements are unsupported in its transaction mode and provides driver-specific configuration guidance; check the exact pooler and client documentation before changing settings. Supabase connection guidance and its pooling documentation describe its setup and behavior.
Use a transaction pooler when the workload consists of compatible, short transactions. If the application needs session affinity, investigate session pooling or direct connections—but only when the resulting client count is safely bounded. Supabase’s endpoints, ports, and pool limits are provider-specific and should be checked in its current documentation rather than generalized to other services. Supabase’s connection and pooling documentation.
When an AWS Lambda workload should consider RDS Proxy
AWS recommends RDS Proxy for production Lambda-to-RDS connections, particularly when functions frequently establish short-lived connections or open and close large numbers of connections. The proxy pools and multiplexes database connections so application-side demand does not have to translate one-for-one into open database sessions. AWS Lambda’s RDS guidance describes the proxy’s role.
A proxy does not create unlimited database capacity. Its capacity settings govern behavior when demand exceeds available connections: requests may queue, be throttled, or be rejected. Account for that behavior in application timeouts, retries, and error handling, and monitor proxy demand alongside database connections and application failures. AWS explains RDS Proxy behavior and capacity.
AWS’s documented automatic Lambda-to-RDS console setup requires the function and database to be in the same VPC. That requirement describes that setup path, not every possible way to connect Lambda to a database. AWS’s setup instructions.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Validate the change without trading exhaustion for timeouts
- Compare the expected peak demand—concurrent instances multiplied by each instance’s pool maximum—with database capacity and other consumers.
- Check whether client connections are reused across invocations within warm instances.
- Confirm that the selected endpoint and pooling mode support the driver’s prepared-statement and session-state requirements.
- Under realistic burst concurrency, watch connection counts, local pool waits, request latency, connection errors, and proxy queueing, throttling, or rejection.
- If requests now wait or fail at a pooler or proxy, adjust concurrency, timeouts, retries, or capacity based on measured behavior rather than simply increasing every pool limit.
A pooler or proxy can absorb connection churn and control how sessions reach PostgreSQL, but it cannot make unlimited demand sustainable. If demand still exceeds the available capacity, the result may be longer waits or rejected work rather than an exhausted database.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




