PgBouncer & connection pool calculator
Enter your CPU, RAM, workload, and peak concurrency to get a safe PgBouncer configuration - default_pool_size, max_client_conn, pool mode - and the Postgres max_connections you actually need behind it. The math is shown, and it all runs in your browser.
- Runs in your browser No server round-trip
- No sign-up Nothing to install
- Nothing is uploaded Your SQL never leaves the tab
- Works offline After the page loads
cores × 2 active connections, throughput drops from lock and context-switch overhead.pgbouncer.ini
[databases]
; point this at your Postgres instance
* = host=YOUR_DB_HOST port=5432
[pgbouncer]
pool_mode = transaction
default_pool_size = 9
min_pool_size = 3
reserve_pool_size = 2
max_client_conn = 1000
server_idle_timeout = 600
query_wait_timeout = 120
; and in postgresql.conf:
; max_connections = 21A small pool in front of many clients
Opening a Postgres connection is expensive - each backend is a process with its own memory. A pooler keeps a small set of warm server connections and shares them across thousands of short-lived client connections.
Without a pooler | With PgBouncer (transaction) | |
|---|---|---|
| Each client opens a real Postgres backend | ||
| max_connections must equal peak clients | ||
| Memory scales with client count | ||
| Thousands of clients on a small pool | ||
| Connection setup cost per request | High | Amortised |
| Safe for serverless / edge bursts |
Connection-pool mistakes that cause outages
Setting the pool as big as your traffic
A pool of 500 doesn't serve 500 requests faster than a pool of 20 - it serves them slower, because the database thrashes. Size for active work (~cores x 2), not for peak client count.
max_connections set to thousands
Every allowed connection reserves memory headroom. A huge max_connections wastes RAM and lets a connection storm actually happen. Behind a pooler it should be small.
Transaction pooling with session features
In transaction mode you can't rely on session state persisting - server-side SET, session advisory locks, and plain prepared statements break. Use them only in session mode, or make your app stateless per transaction.
No client-side pool either
PgBouncer pools server connections; your app should still pool its connections to PgBouncer (e.g. via pg Pool, HikariCP). Opening a fresh client connection per request wastes the pooler's benefit.
Ignoring idle-in-transaction connections
A connection left idle mid-transaction holds locks and a pool slot hostage. Set idle_in_transaction_session_timeout so a forgotten transaction can't wedge the pool.
One giant pool for every service
If several services share a database, give each its own pool sized to its needs, so a runaway service can't starve the others of connections.
Connection pooling FAQ
How big should my PostgreSQL connection pool be?
Smaller than most people think. Throughput is best when active connections are roughly your CPU core count times two - a common formula is (cores * 2) + 1. Beyond that, extra connections spend their time contending for locks and CPU rather than doing work, so a bigger pool is actually slower. This calculator applies that rule and adjusts it for your workload type.
What is the difference between max_client_conn and default_pool_size in PgBouncer?
max_client_conn is how many connections your applications can open to PgBouncer - it can be large (thousands). default_pool_size is how many real connections PgBouncer opens to Postgres per database/user pair - it should be small. The whole point of pooling is that a big number of client connections is multiplexed onto a small number of server connections.
Should I use transaction or session pooling?
Transaction pooling is the right default for web/OLTP apps: a server connection is assigned only for the duration of a transaction, so a small pool serves huge concurrency. Use session pooling if you rely on session-level features (prepared statements without protocol-level support, LISTEN/NOTIFY, advisory locks, SET commands that must persist) - common in analytics or legacy apps.
Do I still need to set max_connections in Postgres if I use PgBouncer?
Yes, but it can be small. Postgres only ever sees the pooler's server connections, so max_connections just needs to cover the pool size plus a few reserved and superuser slots - not your total client count. Setting max_connections to thousands wastes memory (each connection reserves work_mem headroom) and is a common misconfiguration.
Where does PgBouncer run?
Usually as a lightweight process next to your database or your app. Managed platforms often run it for you and give you a separate pooled connection string (frequently on port 6432). If you're on Swyftstack, pooling is handled for you - you just use the connection string.
Related developer tools
More free, browser-only tools for PostgreSQL and cloud storage.
Paste an EXPLAIN ANALYZE plan and get an interactive tree, slow-node highlighting, row-estimate checks, and plain-English fixes.
Open toolBuild or decode a DATABASE_URL and generate ready-to-paste snippets for Node, Python, Go, Rust, Java, and PHP.
Open toolFind a safe max_connections and shared_buffers from your instance RAM, with per-connection memory accounted for.
Open toolCompare AWS S3, Cloudflare R2, Backblaze B2, Google Cloud, Azure, and Supabase side by side - storage, egress, and requests, with charts.
Open toolPooling, handled for you.
Swyftstack runs managed PostgreSQL with connection pooling built in - you just use the connection string. Deployed in under a minute.