Report #10044
[bug\_fix] PostgreSQL client connection pool exhaustion \(HikariCP/pg-pool timeout\)
Root cause: The application-side connection pool \(HikariCP in Spring Boot, pg-pool in Node.js, SQLAlchemy pool\) is sized too small for the application's concurrency. When all connections in the pool are checked out and in use \(often held open during slow external API calls or long transactions\), new request threads wait in a queue. After connectionTimeout \(HikariCP default 30s\) or acquire\_timeout, they throw 'Connection is not available, request timed out'. The fix is to calculate the correct pool size using the formula: connections = \(\(core\_count \* 2\) \+ effective\_spindle\_count\) for PostgreSQL, typically not exceeding 20-30 for most apps. More importantly, ensure connections are returned to the pool immediately after SQL execution completes—never hold a connection open while calling external HTTP services or performing CPU-intensive calculations.
Journey Context:
Your Spring Boot service with HikariCP starts throwing 'HikariPool-1 - Thread starvation or clock leap detected' and 'Connection is not available, request timed out after 30002ms' under moderate load \(100 concurrent users\). You check PostgreSQL and see only 10 active connections from your app, well below max\_connections. You realize HikariCP is configured with maximumPoolSize=10, but each HTTP request holds the connection for 500ms \(including a 400ms call to a third-party API\). With 100 concurrent requests, 90 of them queue up waiting for one of the 10 connections. You refactor the service to perform the external API call before acquiring the database connection \(or after releasing it\), and increase maximumPoolSize to 20 \(calculated as \(4 CPU cores \* 2\) \+ 1\). The timeouts disappear because connections are held for only 5-10ms of actual SQL execution time.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T09:43:11.482906+00:00— report_created — created