Connection Pooling
Overview
Connection pooling is a cache of database connections maintained so that the connections can be reused when future requests to the database are required. Opening a new database connection is computationally expensive and slow; pooling mitigates this overhead.
Key Concepts
Establishing a TCP connection, performing the TLS handshake, and authenticating a database user requires multiple network round-trips. When a web server processes thousands of requests per second, creating a new connection for each request would overwhelm the database with handshake overhead and exhaust its memory.
A Connection Pool solves this by:
- Creating a fixed number of connections on startup (the "pool").
- When the application needs to query the database, it borrows a connection from the pool.
- Once the query finishes, the application returns the connection to the pool instead of closing it.
- If all connections are busy, new requests wait in a queue until one is returned.
Application vs. Proxy Pooling
| Type | Where it lives | Pros | Cons |
|---|---|---|---|
| Application-side | Inside the application process (e.g., HikariCP) | Lowest latency, easy to configure per app | Doesn't scale well with Serverless/Lambda (each instance opens its own pool) |
| Proxy-side | A standalone middle tier (e.g., PgBouncer, ProxySQL) | Multiplexes thousands of client connections into a few DB connections | Adds an extra network hop and architectural complexity |
Trade-offs
Pool sizing is a critical tradeoff. A pool that is too small leaves application threads blocked waiting for a connection, increasing latency. A pool that is too large exhausts the database's memory and CPU, causing thrashing (where the DB spends more time context-switching between connections than executing queries). Surprisingly, a smaller pool (e.g., roughly 2x to 4x the number of CPU cores on the DB) often yields higher overall throughput than a massive pool.
Interview Tips
- If an interview question involves Serverless architectures (like AWS Lambda) hitting a relational database, immediately bring up the connection exhaustion problem. Lambdas scale out massively and can overwhelm the DB; propose a proxy (like AWS RDS Proxy or PgBouncer).
- Mention that connection pools are usually configured with idle timeouts to reap dead connections and keep-alives to prevent firewalls from dropping silent TCP connections.
Summary
- Opening new database connections per request is too slow and expensive.
- Connection pooling reuses a fixed set of open connections to eliminate handshake overhead.
- Pools can live in the application (libraries) or as a separate infrastructure layer (proxies).
- Serverless functions often require proxy-side pooling to prevent connection exhaustion.
- Bigger pools aren't always better; too many connections cause database thrashing.