SYSTEM Cited by 2 sources
PgBouncer¶
What it is¶
PgBouncer (pgbouncer.org) is a lightweight open-source connection pooler for Postgres, widely deployed in production Postgres environments to reduce the cost of short-lived client connections. It speaks the Postgres wire protocol on both sides — clients connect to PgBouncer as if it were Postgres, and PgBouncer multiplexes their queries across a pool of real server-side Postgres connections.
Three pooling modes:
- Session pooling — client holds the server connection for the life of its client-side connection; most transparent, least resource savings.
- Transaction pooling — server connection released back
to the pool at
COMMIT/ROLLBACK; most common production default; breaks features that rely on session state (prepared statements,SET, temp tables, cursors). - Statement pooling — server connection released after each statement; incompatible with multi-statement transactions.
Transaction pooling is the standard production trade-off —
10-100× more clients per server connection, with the
prepared-statement / session-state breakage handled via
client-side workarounds (protocol-level PREPARE rewrites,
SET LOCAL migrations, etc.).
Seen in¶
-
— Canonical wiki framing of connection pooling as the primary RSS-reduction lever for Postgres. Simeon Griggs (PlanetScale, 2026-03-30) writes verbatim: "Efficient connection pooling can be the best way to reduce RSS usage. Fewer active connections result in fewer copies of all that per-process overhead." Companion piece to the sibling Dicken 2026-04-21 configuration-hierarchy post: Dicken documents the connection-count reduction itself (the mechanism); Griggs names the downstream RSS reduction (the memory consequence). Reinforces transaction-mode pooling as the default PlanetScale PgBouncer configuration — transaction-returned connections cut the backend-count multiplier across
work_memallocations, catalog caches, and cached plan / prepared-statement state. Implicitly framed as a cheaper RSS-reduction lever than tuningwork_mem— the post's operational discipline rules explicitly disclaimwork_memtuning as a default change. -
sources/2026-04-21-planetscale-scaling-postgres-connections-with-pgbouncer — canonical wiki disclosure of the PgBouncer configuration surface. Ben Dicken (PlanetScale, 2026-03-13) walks the full connection chain —
max_client_conn→default_pool_size→max_db_connections/max_user_connections→ Postgres-sidemax_connections+superuser_reserved_connections— and formalises the sizing arithmetic asnum_pools × default_pool_size ≤ max_db_connections ≤ max_connections − reserved_slack. Three canonical PlanetScale deployment topologies (concepts/pgbouncer-deployment-topology): (1) local PgBouncer on the same server as the primary (port6432, same credentials, shares failure domain with primary); (2) dedicated primary PgBouncer on separate nodes, "client connections persist through resizes, upgrades, and most failovers" — invoked by appending|your-pgbouncer-nameto username, stitches through the local bouncer; (3) dedicated replica PgBouncer routing to replicas, bypassing the local bouncer. Three pooling modes re-canonicalised with Dicken's unequivocal verdict: "Transaction pooling is the only sensible option" — session pooling is 1:1 and "does little to reduce Postgres connection count"; statement pooling "disallows multi-statement transactions entirely. Most apps need this, so not useful in 99% of cases!"; transaction pooling is the default with the known unsupported-features fallback (LISTEN, session-levelSET/RESET, SQLPREPARE/DEALLOCATE). PlanetScale only supports transaction pooling. Canonicalquery_wait_timeoutdefault: 120 seconds, queue-then-disconnect semantics. Canonical 5+ MB RAM per Postgres connection datum — specific number behind the general "memory overhead" framing in Dicken's sister 2025-09-24 Processes and Threads post. Three worked sizing scenarios (PS-80 / M-2650 / M-1280) instantiate the three-pool-size budget allocation pattern with operator-facing numbers; the single-tenant-per-DB M-1280 scenario inverts the typical multi-tenant sizing intuition, makingdefault_pool_size(notmax_user_connections) the load-bearing dial. Two canonical multi-PgBouncer patterns: layered PgBouncer (app-side funnel + DB-side funnel) and isolated PgBouncer per workload (independent PgBouncer per web/worker/analytics class). Dicken's compose-with-Traffic-Control framing: "PgBouncer manages connections, Traffic Control manages resource consumption. The two approaches complement each other well." Neki referenced as future-generation Postgres- scaling substrate: "Though there are upcoming systems like Neki which will solve this problem in a more robust way, PgBouncer has proven itself an excellent connection pooler for Postgres." -
— PgBouncer named as a component of PlanetScale's proprietary proxy layer for PlanetScale for Postgres: "connection pooling via our proprietary proxy layer, which includes PgBouncer for connection pooling." PgBouncer is the pooling engine inside the proprietary proxy; the proxy also adds query buffering and automatic-failover integration that PgBouncer alone doesn't provide. First canonical wiki instance of PgBouncer-as-pooling-engine-inside-vendor- proxy. — canonical wiki account of PgBouncer on Kubernetes and the latency implications thereof. Alexander Kukushkin (Zalando, 2020-06-23) establishes: (1) PgBouncer is the Zalando Postgres Operator 1.5 default pooler, chosen over Pgpool-II / Odyssey / pgagroal for maturity and simplicity; (2)
so_reuseport(so reuseport pgbouncer scaling) is the canonical PgBouncer multi-core scaling primitive — "essentially a way to get PgBouncer to use more CPU cores"; (3) hyperthread placement matters — two PgBouncer instances on sibling HTs of a single physical core show ~2× the latency of one PgBouncer on an isolated physical core, traceable viaperftracepoints to softirq NET_RX / NET_TX contention; (4) the Kubernetes CPU Manager static policy is the fix; (5) iptables kube-proxy produces visibly non-uniform load across PgBouncer pods (977/995/585/993 m CPU cores across four pods); (6) Zalando's default operator topology is the
AZ-spread Deployment + Service, with the big pooler affinity + small pooler HA pattern as the documented escape hatch for latency-sensitive workloads. First PgBouncer-on-Kubernetes source on the wiki — complements the PlanetScale altitude (dedicated-server Postgres, non-Kubernetes operational model) with the cloud-native / K8s-operator view.
Caveats¶
- PgBouncer is a single-process daemon by default. Multi-instance deployments need external coordination; HA + scaling of PgBouncer itself is an operator responsibility.
- Prepared statements + transaction pooling is an
ongoing ecosystem friction point. Postgres 14 added
protocol-level prepared-statement support in PgBouncer
(via
pg_typecaching mode), but older versions + non-standard clients still break. - Alternative poolers exist —
pgcat(Rust, multi- threaded, sharding-aware), Odyssey (Yandex, TLS-terminating pooler), Supavisor (Supabase, Elixir). PgBouncer remains the canonical default.
Related¶
- systems/postgresql
- systems/planetscale-for-postgres
- systems/planetscale
- systems/planetscale-traffic-control — complementary resource-consumption-axis enforcement; "PgBouncer manages connections, Traffic Control manages resource consumption."
- systems/neki — Dicken's named future-generation successor.
- systems/hyperdrive — Cloudflare's connection-pooling primitive for Workers-to-Postgres, sibling shape at a different altitude.
- systems/dbproxy-figma — Figma's application-layer Postgres router, composes with PgBouncer-style pooling.
- companies/planetscale
- concepts/pgbouncer-connection-chain / concepts/pgbouncer-pool-sizing-formula / concepts/query-wait-timeout / concepts/reserved-admin-connection-budget / concepts/pgbouncer-deployment-topology — the configuration-surface concept quintet canonicalised in the 2026-03-13 Dicken ingest.
- patterns/layered-pgbouncer-deployment / patterns/isolated-pgbouncer-per-workload / patterns/three-pool-size-budget-allocation — multi-PgBouncer and sizing patterns also canonicalised in the same ingest.
- patterns/two-tier-connection-pooling — general two-tier pattern; layered-PgBouncer is the both-tiers-are-PgBouncer instance. companies/zalando — the Kubernetes-operator altitude from the 2020-06-23 Zalando ingest. hyperthread softirq contention · cpu manager static policy · kube proxy iptables probability · process per connection postgres · getsnapshotdata o n — Kubernetes / kernel-level concepts canonicalised in the Zalando ingest. fixed cpu pinning for latency sensitive pool · so reuseport multi process single port · big pooler affinity plus small pooler ha — K8s-deployment patterns from the same ingest.