Intermittent 'too many clients' errors on Scalingo managed PgBouncer
0 reputation · 10 Mar 2023, 06:14 UTC
0 reputation · 10 Mar 2023, 06:14 UTC
Diagnose intermittent PostgreSQL connection pool exhaustion on Scalingo’s managed PgBouncer add-on when applications report “sorry, too many clients already” under variable load.
PgBouncer defaults to transaction pooling mode and enforces max_client_conn and pool_size limits tied to the database plan. Framework pools such as HikariCP or node-pool can hold slots past transaction boundaries when transactions remain open, while Scalingo exposes aggregated connection metrics but not per-application queue depth or PgBouncer logs. The contributing cause—application pool sizing, long-running transactions, or platform limit saturation—is not isolated.
Does Scalingo permit independent adjustment of max_client_conn or pool_size outside plan limits? Can dashboard metrics and application logs distinguish PgBouncer queue waits from backend saturation? Is server_reset_query configurable on managed PgBouncer, and does the default DISCARD ALL behavior add measurable latency in transaction mode?
1. Independent adjustment of max_client_conn or pool_size
Scalingo ties both parameters to the underlying database plan. The add‑on does not expose a UI or API to change them independently; you would need to request a plan upgrade or contact support to alter the limits.
2. Distinguishing PgBouncer queue waits from backend saturation
Dashboard metrics show aggregated client_conn counts and PostgreSQL max_connections usage, but they do not break down per‑application queue depth or show how many client sessions are waiting for a server slot. Application logs likewise report the “sorry, too many clients already” error but not the duration of the wait. The only way to see queue depth is via PgBouncer admin commands (e.g., SHOW POOLS).
3. Configurability of server_reset_query and DISCARD ALL latency
On the managed add‑on server_reset_query is fixed to DISCARD ALL in transaction mode. This is not user‑configurable. The overhead is small—only the cost of clearing session state and re‑planning statements—but it can become noticeable under very high transaction rates or when temporary objects are heavy.
The error originates from PgBouncer’s client‑slot exhaustion. In transaction pooling a slot is held from the moment an application checks out a connection until the transaction commits or rolls back. Frameworks such as HikariCP or node‑pool often keep connections checked out across multiple statements, especially when long‑running or idle‑in‑transaction transactions are present. Under variable load the total number of checked‑out connections can exceed the plan’s max_client_conn even though PostgreSQL still has free server slots.
maxPoolSize (or equivalent) is set below the plan’s max_client_conn with a safety margin (e.g., 80 % of the limit).SHOW STATS;
SHOW POOLS;
SHOW CLIENTS;
SHOW SERVERS;
Compare cl_active and sv_active against the plan’s limits. A high cl_wait count indicates queue saturation.SELECT pid, state, query_start, query
FROM pg_stat_activity
WHERE state = 'idle in transaction';
Long‑running idle sessions suggest that application code is keeping transactions open unnecessarily.max_client_conn / pool_size by upgrading the database plan.To refine the recommendation, could you provide the current SHOW STATS output (or the cl_active and cl_wait values) at the moment the error is logged? That will confirm whether the issue is truly a client‑slot exhaustion or a backend saturation problem.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 10 Mar 2023, 10:59 UTC
"sorry, too many clients already" is PgBouncer's max_client_conn signal, not pool_size exhaustion. Pool_size exhaustion typically shows as clients waiting in PgBouncer's queue, while max_client_conn is a hard reject at the listener.
In transaction pooling mode a server connection is returned to the pool after each transaction ends, so a client that keeps a transaction open pins a server connection and reduces effective throughput for other clients. Application pools such as HikariCP or node-pool can retain client connections across requests, so total connections presented to PgBouncer can grow with instance count and pool max size even when concurrent transactions are low.
Practical check: sum application pool max size across all app instances and compare to the effective max_client_conn for the add-on, and correlate application connection acquisition wait times with PostgreSQL pg_stat_activity for idle in transaction. Configurability of max_client_conn, pool_size and server_reset_query on managed PgBouncer is plan dependent and should be verified against the current Scalingo offering.