Pooling Basics
Each PostgreSQL backend is a process with memory overhead. Raising max_connections without pooling increases context switching and cache churn; PgBouncer multiplexes clients to fewer server backends on PostgreSQL 18.4.
Search across all documentation pages
Each PostgreSQL backend is a process with memory overhead. Raising max_connections without pooling increases context switching and cache churn; PgBouncer multiplexes clients to fewer server backends on PostgreSQL 18.4.
Quick-reference recipe card - copy-paste ready.
SHOW max_connections;
SELECT count(*) AS active_backends FROM pg_stat_activity WHERE backend_type = 'client backend';
-- sizing heuristic (OLTP): pool_size ~= (CPU cores * 2) + effective_spindle_count
-- validate with p95 latency, not app instance countWhen to reach for this: Connection count approaches max_connections, or CPU idle while queries queue in pool wait.
SELECT
setting::int AS max_connections,
(SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend') AS current,
setting::int - (SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend') AS headroom
FROM pg_settings
WHERE name = 'max_connections';
SELECT state, count(*)
FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY state
ORDER BY count DESC;Pair with PgBouncer SHOW POOLS (admin console) to see cl_active, cl_waiting, and sv_active.
What this demonstrates:
work_mem potential per query and private caches.| Metric | Healthy | Investigate |
|---|---|---|
cl_waiting in PgBouncer | Near 0 | Sustained > 0 |
| CPU utilization | Moderate under load | Low CPU, high wait |
max_connections usage | < 70% peak | > 85% peak |
SELECT usename, application_name, state, wait_event_type, query_start
FROM pg_stat_activity
WHERE backend_type = 'client backend'
ORDER BY query_start NULLS LAST
LIMIT 20;idle_in_transaction_session_timeout.| Alternative | Use When | Don't Use When |
|---|---|---|
| PgBouncer | General OLTP multiplexing | Need session-scoped temp tables everywhere |
| Odyssey / pgpool | Vendor-specific features | Simple PgBouncer suffices |
| RDS Proxy | Managed AWS fleets | Self-managed K8s with PgBouncer |
Often 2-4 for OLTP start; measure latency under load.
No, but too few backends cap concurrent queries; balance wait vs CPU.
Reserve superuser slots; exclude admin from app pools.
Pooler or app can terminate TLS; align with compliance.
Stagger pod starts; pooler absorbs burst better than raw Postgres.
Server shows backends; pooler shows client wait queue.
Separate pool per target host/route.
Use both: app pool modest, central PgBouncer for server protection.
Start conservative; increase only with memory model proof.
PgBouncer modes: session vs transaction pooling.
Stack versions: This page was written for PostgreSQL 18.4 (stable 18, maintenance 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x, and PostGIS 3.5+.
Reviewed by Chris St. John·Last updated Jul 18, 2026