PgBouncer Modes
PgBouncer pool_mode decides when a server connection returns to the pool. Transaction pooling maximizes density; session pooling maximizes compatibility on PostgreSQL 18.4.
Search across all documentation pages
PgBouncer pool_mode decides when a server connection returns to the pool. Transaction pooling maximizes density; session pooling maximizes compatibility on PostgreSQL 18.4.
Quick-reference recipe card - copy-paste ready.
; pgbouncer.ini
[databases]
appdb = host=127.0.0.1 port=5432 dbname=appdb
[pgbouncer]
pool_mode = transaction
default_pool_size = 50
max_client_conn = 2000When to reach for this: Choosing pool mode for a new service or debugging prepared statement already exists errors.
-- Session mode: SET and temp tables persist for client connection lifetime
SET search_path = app, public;
CREATE TEMP TABLE staging (id int);
-- OK in session pooling until disconnect
-- Transaction mode: server connection may switch after COMMIT
BEGIN;
SET LOCAL statement_timeout = '5s';
SELECT count(*) FROM orders;
COMMIT;
-- SET LOCAL is safe; session-level SET without LOCAL is riskyVerify mode with PgBouncer admin: SHOW CONFIG; -> pool_mode.
What this demonstrates:
SET LOCAL vs session SET| Mode | Multiplexing | Temp tables | Prepared stmts |
|---|---|---|---|
| session | Low | Yes | Yes |
| transaction | High | No | Tricky |
| statement | Highest | No | Broken |
-- Safe pattern in transaction pooling
BEGIN;
SET LOCAL lock_timeout = '2s';
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
COMMIT;DEALLOCATE ALL on checkout - Some drivers need server_reset_query. Fix: Configure server_reset_query = DISCARD ALL where appropriate.| Alternative | Use When | Don't Use When |
|---|---|---|
| session pooling | Heavy temp table ETL in app | Thousands of idle clients |
| RDS Proxy | AWS managed multiplexing | On-prem K8s |
| Direct connect (no pool) | Local dev only | Production fleet |
transaction with SET LOCAL and no temp tables.
Use SET LOCAL inside transaction or connection init via startup params.
DISCARD ALL clears session state between transactions in transaction mode.
See dedicated page; often disable in ORM for transaction mode.
PgBouncer database stanza per target; pools isolated per db/user.
Pooler connects upstream TLS; clients TLS to pooler.
userlist.txt or auth_query for SCRAM with PostgreSQL 18.
COPY in transaction usually OK within single transaction block.
Pooler config update or DNS to new primary; apps reconnect to pooler.
Prepared statements pitfalls in transaction mode.
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 19, 2026