ThisCalculator

Everyday

Connection Pooling vs New Connection per Request

Updated · Standard formula, shown below

Time saved by pooling (s) 19.00 s
Total time with new connections (s)
20.00 s
Result
Total time with pool (s)
1.00 s
Result
Total requests
1000
You entered

Connection Pooling vs New Connection per Request

Connection pooling reuses a set of already-open database connections, while opening a new connection per request creates and destroys a TCP connection (and often a full authentication handshake) for every single request. Pooling is almost always the better choice for web applications because it dramatically reduces latency and server load, but there are specific cases where a fresh connection is acceptable or even necessary.

Formula

The calculator estimates the total time spent establishing database connections for a given number of requests, comparing a new-connection-per-request approach with a pooled approach. The formula is:

Total time (new) = T × C
Total time (pooled) = T × P
Time saved = T × (C − P)

Where:

  • T = total number of requests (dimensionless)
  • C = average time to open a new connection, in milliseconds (ms)
  • P = average time to obtain a pooled connection, in milliseconds (ms)

All times are converted to seconds in the output. The formula assumes that every request needs exactly one database connection and that the pool never runs out of connections (i.e., no queue wait time).

Worked Example

Using the default values: 1,000 requests, a new connection takes 20 ms, and a pooled connection takes 1 ms.

  1. Total time with new connections: 1,000 × 20 ms = 20,000 ms = 20 seconds
  2. Total time with pooling: 1,000 × 1 ms = 1,000 ms = 1 second
  3. Time saved: 20 − 1 = 19 seconds

The calculator shows 19.00 seconds saved, which matches the manual calculation.

Why New Connections Are Slow

Opening a database connection is not a single operation. It involves multiple network round trips and server-side work:

  • TCP handshake: Three packets (SYN, SYN-ACK, ACK) between client and server.
  • TLS/SSL negotiation: If encryption is used, several more round trips to exchange certificates and keys.
  • Authentication: The database server verifies credentials, checks permissions, and may load user-specific settings.
  • Session initialization: The server allocates memory, sets up transaction state, and may run startup queries (e.g., setting timezone or charset).

On a local network, this can take 5–20 ms. Over the internet, it can easily exceed 100 ms. For a busy web app handling hundreds of requests per second, that overhead multiplies quickly.

How Connection Pooling Works

A connection pool is a cache of database connections maintained by the application (or a middleware library). The pool typically:

  1. Creates a fixed number of connections when the application starts (or on demand).
  2. Keeps them open and idle.
  3. When a request needs a connection, it borrows one from the pool.
  4. When the request finishes, the connection is returned to the pool, not closed.

Most pools also validate that a connection is still alive before handing it out, and they can grow or shrink the number of connections based on demand. Common pool libraries exist for every major language: HikariCP for Java, psycopg2 pool for Python, node-postgres pool for Node.js, and so on.

When to Use a New Connection Per Request

There are a few legitimate reasons to skip pooling:

  • Very low traffic: If you have a script that runs once a day and makes a single query, a pool is unnecessary overhead.
  • Short-lived CLI tools: Command-line utilities that run, query, and exit do not benefit from keeping connections open.
  • Specialized environments: Some serverless platforms (e.g., AWS Lambda) may not allow long-lived connections, or the connection cost is already included in the cold-start time.
  • Testing and debugging: Simplicity can be more important than performance in a local dev environment.

However, even in these cases, a pool with a small maximum size (like 2–5) is often still fine and can help if the tool is run repeatedly.

Common Pitfalls and Misconceptions

A frequent mistake is assuming that a pool always makes things faster. A pool can hurt if:

  • Pool size is too small: If all connections are busy, requests queue up and wait, adding latency instead of saving it.
  • Connections go stale: Network firewalls or database timeouts can kill idle connections. A good pool tests connections before use, but this adds a small overhead.
  • Leaked connections: If code forgets to return a connection, the pool eventually exhausts, causing errors. Always use try/finally or a context manager.
  • Misunderstanding “connection” vs “session”: A pooled connection may still have session state (e.g., temporary tables, user variables) that leaks between requests. You must reset state if needed.

Another misconception is that pooling is only for databases. The same principle applies to HTTP connections, SMTP, Redis, and any other network service where establishing a connection is expensive.

Costs and Trade-offs

Pooling saves time and CPU, but it also consumes resources:

  • Memory: Each open connection uses memory on both the client and the database server.
  • Database server load: A pool keeps connections open even when idle, which can exceed the server’s connection limit if misconfigured.
  • Complexity: You need to handle pool timeouts, validation, and cleanup.

In practice, the trade-off is almost always worth it for any application that handles more than a few requests per minute. The default pool sizes in popular frameworks (e.g., 10–20) are usually a good starting point.

How to Choose the Right Pool Size

There is no universal magic number, but a reasonable approach is:

  1. Measure your application’s concurrency: how many requests are in flight at the same time.
  2. Start with a pool size equal to that concurrency, plus a small buffer.
  3. Monitor connection wait time. If requests are waiting, increase the pool size.
  4. Watch database CPU and memory. If the database is saturated, reduce the pool size or add caching.

As a rule of thumb, a pool size of 10–20 is fine for most small-to-medium applications. Large applications with hundreds of concurrent users may need 50–100, but that is rare and usually indicates a need for read replicas or query optimization.

Frequently Asked Questions

Does connection pooling work with serverless functions?
It depends. In AWS Lambda, you can create a pool outside the function handler and reuse it across warm invocations, but each invocation may run on a different container, so the pool is not shared. In some cases, opening a new connection per invocation is simpler and avoids idle connection charges.

Can a connection pool cause data isolation problems?
Yes. If you use session-scoped features like temporary tables, user-defined variables, or row-level security tied to a session, a pooled connection may carry state from a previous request. Always reset session state after borrowing a connection, or use a pool that supports session reset.

What is the difference between a connection pool and a statement cache?
A statement cache stores prepared SQL statements (parsed and optimized) on the server, while a connection pool stores open connections. They are complementary: a pool reduces connection overhead, and a statement cache reduces query parsing overhead. Many pools also include a statement cache.

Is it ever faster to open a new connection?
Only if the pool is misconfigured (e.g., too small, causing queue waits) or if the database is remote and the pool does not keep connections warm. In normal conditions, a pooled connection is 10–100× faster to obtain than a new one.

How do I know if my pool is too large?
If the database server shows high CPU or memory usage while the application is idle, or if you hit the database’s max_connections limit, your pool is likely too large. Reduce the maximum size and monitor again.

Related

Formula used
in t | Total requests | - | 1000 | 1
in c | New connection time (ms) | ms | 20 | 1
in p | Pooled connection time (ms) | ms | 1 | 1
out saved | Time saved by pooling (s) | s | (t * (c - p)) / 1000 | 2
out total_new | Total time with new connections (s) | s | (t * c) / 1000 | 2
out total_pool | Total time with pool (s) | s | (t * p) / 1000 | 2

Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.