CONCEPT Cited by 1 source
PgBouncer connection chain¶
Definition¶
The PgBouncer connection chain is the cascade of configuration caps that govern how client connections reach Postgres through PgBouncer. Each cap bounds a different dimension of the pooling geometry; together they form a funnel from many client-facing connections down to a tightly controlled number of upstream Postgres backend processes.
The chain¶
max_client_conn(PgBouncer) — maximum number of client connections PgBouncer will accept. Connections are lightweight in PgBouncer, so this is frequently set in the thousands or tens of thousands.default_pool_size(PgBouncer) — number of server connections per(user, database)pool. With 4 users × 2 databases = 8 pools anddefault_pool_size=20, PgBouncer could open up to 160 connections to Postgres.max_db_connectionsandmax_user_connections(PgBouncer) — hard caps that span all pools for a given database or user, respectively. Default is0(no limit). Act as safety valves to prevent pool arithmetic from exceeding Postgres limits.max_connections(Postgres) — total server connections must stay below this. "We should always keep a few available direct connections reserved for admin tasks and other emergency scenarios. We NEVER want PgBouncer to use all of the connections!" (Dicken).superuser_reserved_connections(Postgres) — explicit slot reservation for the superuser (distinct from operator discipline of leavingmax_connections − max_db_connectionsslack).
(Source: sources/2026-04-21-planetscale-scaling-postgres-connections-with-pgbouncer.)
Why it's a chain, not a single number¶
Each cap bounds a different dimension:
max_client_conn— client-facing concurrency (inbound).default_pool_size— per-(user, db) pool concurrency.max_user_connections— per-user aggregate across all their pools.max_db_connections— per-database aggregate across all users' pools.max_connections— Postgres-global (total backend processes).
A single cap at any one layer is insufficient: a user-specific cap doesn't prevent another user from exhausting the database; a database-specific cap doesn't prevent one user starving another; a pool-specific cap doesn't coordinate across pools. The chain enforces the right scope at the right layer.
The canonical invariant¶
num_pools × default_pool_size ≤ max_db_connections ≤ max_connections − reserved_slack
The operator's sizing task is to satisfy this inequality with the specific per-user / per-database / admin-reserve margins for their workload. See concepts/pgbouncer-pool-sizing-formula for the detailed arithmetic.
Worked examples¶
Dicken's three scenarios (sources/2026-04-21-planetscale-scaling-postgres-connections-with-pgbouncer) instantiate the chain:
- PS-80 (1 vCPU, 8 GB):
max_client_conn=500 → default_pool_size=30 → max_user_connections=30 / max_db_connections=40 → max_connections=50(10-slot admin reserve). - M-2650 (32 vCPU, 256 GB):
max_client_conn=10000 → default_pool_size=200 → max_user_connections=200 / max_db_connections=450 → max_connections=500(50-slot admin reserve). - M-1280 (16 vCPU, 128 GB, 200 single-tenant DBs):
max_client_conn=5000 → default_pool_size=2 → max_user_connections=2 / max_db_connections=2 → max_connections=400(200 pools × 2 = 400 upstream, equal tomax_connections).
Each scenario sets different dials as load-bearing:
- PS-80 / M-2650:
max_user_connectionsis load-bearing (prevents theappuser from monopolising the pool). - M-1280:
default_pool_sizeis load-bearing (per-pool cap of 2 with 200 pools is the only knob that keeps 200 × size ≤ 400).
Seen in¶
- sources/2026-04-21-planetscale-scaling-postgres-connections-with-pgbouncer — canonical first wiki disclosure of the full chain with worked examples. Ben Dicken (PlanetScale, 2026-03-13) walks each cap in sequence with the arithmetic constraint as the anchor.
Related¶
- systems/pgbouncer — the pooler the chain configures.
- systems/postgresql — the substrate whose
max_connections+superuser_reserved_connectionsare the chain's downstream anchor. - concepts/max-connections-ceiling — the Postgres-side anchor that caps the entire chain.
- concepts/memory-overcommit-risk — the failure mode the chain exists to prevent.
- concepts/connection-pool-exhaustion — the desired graceful-failure mode within the chain.
- concepts/pgbouncer-pool-sizing-formula — the arithmetic formalisation of the chain.
- concepts/query-wait-timeout — the admission-control primitive within the chain (queue-then-disconnect when
default_pool_sizeis saturated). - concepts/reserved-admin-connection-budget — the
max_connections − max_db_connectionsslack discipline. - patterns/three-pool-size-budget-allocation — the sizing pattern that operationalises the chain.
- patterns/two-tier-connection-pooling — the higher-level shape (app-tier + proxy-tier) of which this chain is the within-the-proxy-tier detail.