HikariCP Pool Size Calculator

Pick a maximum-pool-sizefrom numbers you can measure: requests per second, how long each request holds a connection, your thread model and the database's max_connections. The calculator checks the three limits that actually bound a pool — load, deadlock safety and the database cap during a rolling deploy — and gives you the YAML.

Runs entirely in your browser · Updated · by Srue, backend engineer

Load (per app instance)
req/s
ms
%
Threads
threads
conns
Database limits
conns
conns
instances
instances
cores

Recommended maximum-pool-size

7

per instance · 21 connections across 3 instances

How the number was picked

Load-based (Little's law + headroom)
7
Deadlock-safe minimum
1
DB cap per instance (with deploy surge)
35
DB guideline: (cores × 2) + spindles, total
17

Fits within the database limits with room for a rolling deploy.

application.yml

spring:
  datasource:
    hikari:
      maximum-pool-size: 7
      # minimum-idle: leave unset — HikariCP recommends a fixed-size pool
      connection-timeout: 3000     # fail fast instead of the 30 s default
      max-lifetime: 1800000        # keep below the DB / proxy idle timeout

The three numbers that bound a pool

  1. Load.By Little's law, the connections in use at any moment equal the arrival rate times the time each one is held. 200 requests per second that each hold a connection for 25 ms keep about 5 connections busy.
  2. Deadlock safety. If one thread can hold two connections at once — typically a REQUIRES_NEW call inside an open transaction — a pool smaller than Tn × (Cm − 1) + 1 can lock up with every thread holding one connection and waiting for a second. With Cm = 1 the minimum is 1.
  3. The database cap. All instances share one max_connections. Leave room for admin sessions, replication and batch jobs, and count the extra pods that run during a rolling update.

Worked example

With the calculator's default inputs — 200 requests per second per instance, 25 ms hold time, 30% headroom, 3 instances plus 1 during deploys, and a database with 151 max connections of which 10 are reserved:

Worked HikariCP sizing example
CheckCalculationResult
Load-based200 × 0.025 s × 1.37
Deadlock-safe minimum1 connection per thread1
DB cap per instance(151 − 10) ÷ (3 + 1)35
DB guideline (total)8 cores × 2 + 117
Recommendedmax(load, deadlock), capped by the DB7

7 connections per instance looks small next to the default of 10, and that is the point: the service is fast because each request releases its connection quickly. If you need 50, the fix is usually in the transaction, not the pool.

Measuring connection hold time

Don't guess the hold time. With Spring Boot Actuator and Micrometer, HikariCP publishes these metrics for each pool:

HikariCP Micrometer metrics
MetricWhat it tells you
hikaricp.connections.usageHow long connections are held — use the mean or p99 as the hold time
hikaricp.connections.acquireHow long callers wait to get a connection
hikaricp.connections.activeConnections in use right now
hikaricp.connections.pendingThreads waiting for a connection — should stay near zero
hikaricp.connections.timeoutRequests that gave up after connection-timeout

HikariCP defaults worth knowing

HikariCP default settings
Property (spring.datasource.hikari.*)DefaultNote
maximum-pool-size10Per instance
minimum-idlesame as maximumLeave unset for a fixed pool
connection-timeout30000 msMany teams lower it to a few seconds to fail fast
idle-timeout600000 msOnly applies when minimum-idle is below maximum
max-lifetime1800000 msKeep it shorter than any DB or proxy idle timeout
leak-detection-threshold0 (off)Set e.g. 60000 in staging to log leaked connections

When a bigger pool is the wrong fix

  • Remote calls inside a transaction. An HTTP call inside @Transactional holds the connection for the whole round trip. Move it outside the transaction and the required pool size drops with it.
  • Open Session in View. spring.jpa.open-in-view is on by default and keeps a connection for the whole web request, including view rendering. Turning it off often cuts hold time sharply.
  • Slow queries. A query that takes 400 ms instead of 4 ms needs a hundred times the connections at the same traffic. An index is cheaper than a larger database.

Frequently asked questions

What is the default HikariCP pool size in Spring Boot?

maximumPoolSize defaults to 10, and minimumIdle defaults to the same value, so you get a fixed pool of 10 connections per application instance. Spring Boot does not change these defaults; set spring.datasource.hikari.maximum-pool-size to override.

What does “Connection is not available, request timed out after 30000ms” mean?

Every connection in the pool was busy for the whole connectionTimeout (30 seconds by default) and the request gave up. The usual causes are transactions that hold connections too long (remote calls inside @Transactional, slow queries), connection leaks, or a pool that is genuinely too small for the load. Check hikaricp.connections.usage and hikaricp.connections.pending before raising the pool size.

Should minimum-idle be the same as maximum-pool-size?

HikariCP recommends leaving minimumIdle unset so the pool stays fixed at maximumPoolSize. A fixed pool avoids opening connections during a traffic spike, which is exactly when you can least afford the latency.

Is the pool size per application or per instance?

Per instance. Ten replicas with maximum-pool-size 20 can open 200 connections, and during a rolling deploy the old and new pods overlap. Size the pool from the database's max_connections divided by the number of instances you can have at the same time.

Is a bigger connection pool faster?

Usually not beyond a small number. A database can only execute as many queries in parallel as it has CPU cores and I/O capacity; extra connections wait in line and add context switching. The HikariCP wiki suggests starting near (cores × 2) + effective spindles for the database as a whole.

How does this change with virtual threads?

With spring.threads.virtual.enabled=true the number of request threads is effectively unlimited, so the pool becomes the real concurrency limit. Requests queue inside getConnection() instead of in Tomcat. Keep the pool sized for the database, lower connection-timeout so callers fail fast, and watch hikaricp.connections.pending.