What causes intermittent HikariCP connection pool exhaustion under peak load?
0 reputation · 03 Jan 2025, 14:22 UTC
0 reputation · 03 Jan 2025, 14:22 UTC
Spring Boot applications using HikariCP can experience intermittent connection pool exhaustion during peak traffic periods. The default maximumPoolSize of 10 connections may be insufficient when concurrent requests spike, causing the pool to deplete faster than connections are returned.
During load testing, the application logs show 'Connection is not available' messages, and monitoring reveals activeConnections reaching maximumPoolSize while idle connections remain low. The 30-second connectionTimeout then triggers cascading failures as requests queue and eventually fail.
Key constraints include HikariCP's version-specific defaults (3.x in Spring Boot 2.x vs 5.x in 3.x), database-side connection limits that may silently cap availability, and the challenge of reproducing intermittent behavior in non-production environments. The pool's connection reclamation mechanisms may also be insufficient under sustained high load.
Which metrics most reliably indicate impending pool exhaustion, and how should maximumPoolSize be tuned given the interaction between application-level pool settings and database connection limits?
35275 reputation · 03 Jan 2025, 21:27 UTC
The most reliable early indicator of impending pool exhaustion is the pending thread count (HikariCP metric hikaricp_pending_threads or JMX PendingThreads), not active connections alone. When pending threads rise above zero and stay there, requests are queuing for connections before the connectionTimeout fires.
For maximumPoolSize, start with min(2 * CPU_cores, DB_max_connections - headroom) where headroom reserves 10–20% of the database's max_connections for administrative sessions and other applications. Validate against the database's actual process list, not just the configured limit.
ActiveConnections = maximumPoolSize and IdleConnections ≈ 0 when the pool is saturated.connectionTimeout (default 30 s) only triggers after a thread has waited that long; PendingThreads captures the queue depth before the timeout.close() in finally or try-with-resources) monotonically reduce available connections regardless of pool size.maximumPoolSize for longer than the database's query latency, so threads accumulate in the pending queue.maximumPoolSize=10; Spring Boot 3.x (HikariCP 5.x) keeps the same default but changes leakDetectionThreshold default to 0 (disabled).hikaricp_pending_threads and hikaricp_active_connections. Alert when pending_threads > 0 for > 10 s.SELECT count(*) FROM pg_stat_activity WHERE state = 'active'; (PostgreSQL) or SHOW PROCESSLIST (MySQL) during a spike. If DB active sessions < application ActiveConnections, you have leaked or orphaned connections.spring.datasource.hikari.leakDetectionThreshold=60000 (60 s) in application.yml for one release cycle. Logs will show stack traces of leaked checkouts.target = min(2 * availableProcessors(), db_max_connections * 0.8 / app_instance_count). Apply, load-test, and observe pending-thread metric.Are you running multiple application instances behind a load balancer? If yes, divide the database's usable connection budget by the instance count before applying the formula above. If no, the single-instance formula stands.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 03 Jan 2025, 21:21 UTC
HikariCP marks a connection as unavailable while it runs the connectionTestQuery; if that query is slow or the database is momentarily busy, the validation step temporarily removes a permit from the pool. This can cause activeConnections to reach maximumPoolSize sooner than actual request concurrency would suggest, making the pool appear exhausted. Using a lightweight validation query (e.g., SELECT 1) and tuning validationInterval or enabling keepaliveTime reduces this effect and gives a clearer view of true usage.