Connection Pool Fundamentals

A connection pool reuses a bounded set of database connections instead of creating a new connection for every request. This reduces connection-setup overhead and limits how many database connections the application can use concurrently.

A database connection is relatively expensive to establish because it can involve network communication, authentication, session setup, and database-side resources. A connection pool creates a set of connections ahead of time and keeps them available for application code to borrow.

When a request needs the database, it checks out an available connection from the pool. After the database work finishes, the application returns the connection to the pool rather than physically closing it. The next request can reuse that connection.

A pool is bounded: it has a maximum number of connections that can be active at once. If all connections are busy, another request generally waits for one to become available or fails after a configured timeout. This provides an important form of backpressure and prevents unlimited connection creation.

The pool must also manage connection lifetime and health. Depending on the pooling implementation and configuration, connections may be validated, retired after reaching an age or usage limit, or replaced when they become unusable. Application code should still reliably return borrowed connections, typically with Java's `try-with-resources` when the pool integrates with JDBC.

Key points

Interview questions

What problem does a database connection pool solve?

Opening a database connection can be relatively expensive, so creating one for every request adds unnecessary overhead. A connection pool maintains a bounded collection of reusable connections. Requests borrow a connection, perform database work, and return it. Reuse improves efficiency and also limits the number of concurrent database connections.

What happens when the pool has no available connections?

A request normally cannot immediately obtain a connection. Depending on the pool configuration, it waits for a connection to be returned or eventually fails when its acquisition timeout is reached. This prevents the application from creating unlimited database connections. The correct timeout and pool size depend on the application's workload and database capacity.

Why must application code close or release a pooled connection?

The application must signal that it has finished using the connection so the pool can make it available to another request. With JDBC pooling, calling `close()` on the borrowed connection is commonly implemented by the pool as a return-to-pool operation rather than immediate physical destruction. If code fails to release connections, the pool can become exhausted even though the database itself is healthy. `try-with-resources` is a common way to make release happen reliably.

How would you choose a connection pool size?

There is no universally correct pool size because it depends on database capacity, query latency, application concurrency, and the number of application instances. A larger pool does not automatically improve throughput because excessive concurrent database work can increase contention and database load. I would start from the database's connection budget and workload characteristics, then measure acquisition latency, query latency, utilization, and timeout rates under representative load. The final configuration should account for every application instance sharing the database.