Skip to content

Postgres Connection Pool Sizer

Find the right database pool size and max_connections.

Effective spindle count ≈ the number of disks that can service I/O in parallel. For a single SSD or cloud volume, use 1.

Optimal pool size (total)

9

Pool size per instance

2

Suggested max_connections

13

postgresql.conf

max_connections = 13

Set each app instance's pool to 2 (e.g. HikariCP maximumPoolSize, Prisma connection_limit).

A starting point, not a law. A pool smaller than cores×2 often wins under contention; a larger one rarely does. Benchmark under real load and watch for connections stuck waiting.

Enter your Postgres CPU cores, effective spindle count, and number of application instances to get a recommended total pool size, the per-instance connection limit to configure, and the max_connections your server should allow. The base formula — (cores × 2) + effective spindles — comes from the HikariCP wiki and PostgreSQL performance guidance, where it consistently outperforms larger pools.

The counter-intuitive part: a smaller pool is usually faster. Once you have more active connections than the database can run in parallel, extra connections add context-switching and lock contention rather than throughput. Treat the result as a benchmarking starting point, and if you run many instances (especially serverless), put PgBouncer in front so per-instance pools do not exhaust the server.

Frequently asked questions

What is the formula for Postgres connection pool size?

A widely used starting point is connections = (CPU cores × 2) + effective spindle count, popularized by the HikariCP wiki. It reflects that a database can only usefully run a limited number of queries in parallel; beyond that, more connections add contention rather than throughput. Benchmark against your real workload from there.

Why does a smaller connection pool often perform better?

Because the database has a finite number of cores and disks. Once active connections exceed what the hardware can process simultaneously, the extra ones queue and cause context-switching, lock contention, and cache thrashing — reducing throughput and raising latency. A right-sized pool keeps the database busy without overwhelming it.

When do I need PgBouncer?

When many application instances each keep their own pool, or in serverless/edge environments where instance count is unbounded. Direct connections multiply and can exhaust max_connections. PgBouncer in transaction mode multiplexes thousands of client connections onto a small number of real Postgres connections.