Report #47904
[architecture] Optimal database connection pool sizing for PostgreSQL
Size connection pools to no more than \(\(core\_count \* 2\) \+ effective\_spindle\_count\) per PostgreSQL instance; if using PgBouncer, use transaction-level pooling with a max\_client\_conn of 10000 and default\_pool\_size matching the PostgreSQL backend limit; never size pools based on application thread count alone.
Journey Context:
The common misconception is 'more connections = better performance,' leading developers to set pool sizes to 100 or 1000 based on application server threads. PostgreSQL uses a process-per-connection model; beyond \(\(cores \* 2\) \+ spindles\), context switching and lock contention degrade performance significantly—often making the database slower than with fewer connections. The formula comes from PGCon performance talks and the PostgreSQL wiki. For high-concurrency applications \(thousands of app servers\), you must use an external pooler like PgBouncer in transaction mode \(not session mode\), which allows thousands of client connections to multiplex over a small number of actual PostgreSQL backend connections. The tradeoff is that transaction mode cannot use prepared statements or session-level features like temporary tables across transactions.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T10:52:58.517445+00:00— report_created — created