Connection Pooling Cheat Sheet
Explains why database connection pooling matters, how pool sizing works, and configuration patterns for tools like PgBouncer and application-level pools.
2 PagesIntermediateMar 15, 2026
Why Connection Pooling
The problem pooling solves.
- Connection overhead- Opening a new TCP + auth handshake per request can take 5-50ms and consumes real server memory (a few MB per connection)
- Max connections limit- Databases cap concurrent connections (e.g., Postgres default max_connections=100); each idle connection still reserves memory
- Pool- A cache of already-open, reusable connections that the application borrows and returns instead of opening a fresh one per query
- Thundering herd- Without pooling, a traffic spike can open thousands of simultaneous connections and crash the database
- External vs application pooling- Application pools (e.g., HikariCP, node-postgres Pool) live inside your app process; external poolers (PgBouncer, ProxySQL) sit between many app instances and the DB
PgBouncer Configuration
A minimal transaction-pooling setup.
ini
[databases]mydb = host=127.0.0.1 port=5432 dbname=mydb[pgbouncer]listen_port = 6432listen_addr = *auth_type = md5auth_file = /etc/pgbouncer/userlist.txt# transaction pooling: connection is returned to the pool after each transactionpool_mode = transactionmax_client_conn = 1000default_pool_size = 20reserve_pool_size = 5
Node.js Application Pool
Configuring and using node-postgres's Pool.
javascript
const { Pool } = require('pg');const pool = new Pool({ host: 'localhost', database: 'mydb', max: 20, // max connections in the pool idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000,});// Borrow a connection, run a query, return it automaticallyconst result = await pool.query('SELECT * FROM orders WHERE id = $1', [42]);// Always release manually-checked-out clientsconst client = await pool.connect();try { await client.query('BEGIN'); await client.query('UPDATE accounts SET balance = balance - 100 WHERE id = 1'); await client.query('COMMIT');} finally { client.release();}
Pool Sizing & Modes
How pooling modes trade off compatibility for reuse.
- Session pooling- Client holds the same server connection for the whole session; safest but least efficient reuse
- Transaction pooling- Connection is returned to the pool after each transaction commits; higher reuse but breaks session-level features (e.g., prepared statements, advisory locks)
- Statement pooling- Connection returned after every single statement; most aggressive, incompatible with multi-statement transactions
- Pool size formula- A common starting point is connections = ((core_count * 2) + effective_spindle_count); oversized pools cause context-switch thrashing on the DB, not more throughput
- Connection leaks- Forgetting to release/close a checked-out connection exhausts the pool over time; always release in a finally block
Pro Tip
More pool connections rarely means more throughput — past a certain point (often surprisingly low, like 2x CPU cores plus disk count) additional connections just queue on the database's internal lock manager; benchmark before scaling the pool size up.
Was this cheat sheet helpful?
Explore Topics
#ConnectionPooling#ConnectionPoolingCheatSheet#Database#Intermediate#WhyConnectionPooling#PgBouncerConfiguration#NodeJsApplicationPool#PoolSizingModes#Databases#CheatSheet#SkillVeris
Advertisement
Sri Hayavadhana Info-Tech
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance