← Concepts

阅读中文版本

Connection Pool Sizing

Connection pool sizing sets the min, max, and acquire timeout so the pool serves peak concurrency without exhausting the database, and a spike waits rather than opening unbounded connections.

performance

Definition

Connection pool sizing is the configuration of the minimum (keep-alive baseline), maximum (bound on database connections), and acquire timeout (how long a caller waits for a free connection) so that the pool serves the peak concurrency without exceeding the database connection limit and a spike waits rather than opening unbounded connections that crash the database.

Context and scope

Applied in every service that connects to a database, where too few connections starve throughput and too many exhaust the database.

Common misconceptions

  • A larger pool is always faster — it is faster up to the database limit; past that, the database spends more time on connection management than on queries and throughput drops
  • The pool size should equal the thread count — the pool should match the concurrency that issues queries; a pool larger than the concurrency wastes idle connections

Anti-patterns

  • Setting the pool max to the thread count with no acquire timeout, so a spike blocks every thread waiting for a connection
  • Sharing one large pool across tenants, so one tenant spike exhausts the pool for everyone

Related concepts

Authoritative source

https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

What it is

Connection pool sizing is the configuration of the minimum (keep-alive baseline), maximum (bound on database connections), and acquire timeout (how long a caller waits for a free connection) so that the pool serves the peak concurrency without exceeding the database connection limit and a spike waits rather than opening unbounded connections that crash the database. Applied in every service that connects to a database, where too few connections starve throughput and too many exhaust the database. Performance is a distribution, not a number: the tail determines user experience, and the mean hides the outliers that cause abandonment.

How it works

Measurement targets percentiles at the workload’s actual concurrency, not a single sequential run. The fast path is kept fast by deferring work that is not on it — lazy initialization, coalescing writes, avoiding allocation in hot loops. Profiling finds the bottleneck; micro-optimization without a profile optimizes the wrong thing. Constant factors matter, but algorithmic complexity dominates as scale grows.

When to optimize and pitfalls

Optimize when a measurement shows a concrete cost — latency budget burn, compute spend, user-visible jank. The pitfall is optimizing for the benchmark rather than the workload: a synthetic test that does not reproduce the production access pattern produces a local maximum that hurts globally. Another is trading memory for speed without accounting for the GC or eviction cost the extra allocation introduces.