Careeroza
Connection Pooling with HikariCP
Why a Pool
Opening a database connection takes 20 to 100 ms (TCP, TLS, login). A connection pool opens a few connections at startup and lends them to requests. Spring Boot uses HikariCP by default.
Example
A pool is like a counter with N tokens. Here 2 "connections" serve 5 requests; extra requests wait for a free connection. A Semaphore models it:
import java.util.*;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
Semaphore pool = new Semaphore(2); // maximum-pool-size = 2
ExecutorService requests = Executors.newFixedThreadPool(5);
List<Future<String>> results = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
int id = i;
results.add(requests.submit(() -> {
boolean waited = !pool.tryAcquire();
if (waited && !pool.tryAcquire(2, TimeUnit.SECONDS)) return "request " + id + ": timeout";
try {
Thread.sleep(100); // run the SQL query
return "request " + id + (waited ? ": waited for a connection" : ": got a connection immediately");
} finally {
pool.release();
}
}));
Thread.sleep(10); // requests arrive one after another
}
for (Future<String> f : results) System.out.println(f.get());
requests.shutdown();
}
}Output
request 1: got a connection immediately request 2: got a connection immediately request 3: waited for a connection request 4: waited for a connection request 5: waited for a connection
Tuning Hikari
Example
application.yml
spring:
datasource:
url: jdbc:mysql://${DB_HOST:localhost}:3306/shopease
username: ${DB_USER}
password: ${DB_PASSWORD}
hikari:
maximum-pool-size: 20 # total connections per instance
minimum-idle: 5
connection-timeout: 3000 # ms to wait for a free connection, then fail fast
idle-timeout: 600000
max-lifetime: 1800000 # below the DB's wait_timeout
leak-detection-threshold: 20000
pool-name: shopease-hikari- Bigger is not better. A good start:
connections = (CPU cores of the DB × 2) + disks, often 10 to 30. - Multiply by the number of app instances: 6 pods × 20 = 120 connections. Check the database's
max_connections. - Watch
hikaricp_connections_pendingin metrics. If requests often wait, find slow queries before increasing the pool.
Keep Transactions Short
Note: A connection is held for the whole @Transactional method. Never call a slow HTTP API (payment, SMS) inside a transaction: the connection sits idle while you wait, and the pool runs dry. Also set spring.jpa.open-in-view=false so connections are not held while the JSON response is written.