Free developer tool

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
9
default_pool_size
1000
max_client_conn
transaction
pool_mode
21
Postgres max_connections
With a pooler in transaction mode, 500 client connections are multiplexed onto just 9 real Postgres connections - so Postgres itself only needs max_connections = 21, not 500. A small, busy pool beats a large idle one: past roughly 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 = 21
Why pooling

A 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 requestHighAmortised
Safe for serverless / edge bursts
Get it right

Connection-pool mistakes that cause outages

01

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.

02

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.

03

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.

04

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.

05

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.

06

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.

Pooling, handled for you.

Swyftstack runs managed PostgreSQL with connection pooling built in - you just use the connection string. Deployed in under a minute.