Connection Pool Exhausted? It's Likely Leaked Connections, Not Database Limits

This guide diagnoses database connection pool exhaustion by distinguishing connection leaks from genuine high concurrency, demonstrating log analysis for HikariCP and Druid, verifying leaks via SHOW PROCESSLIST and pool metrics, fixing code with try-with-resources, tuning key HikariCP parameters, and enabling leak detection to pinpoint exact leak locations.

Engineer Tang's Implementation Study Notes
Engineer Tang's Implementation Study Notes
Engineer Tang's Implementation Study Notes
Connection Pool Exhausted? It's Likely Leaked Connections, Not Database Limits

The article opens with a real-world symptom: a device data reporting API suddenly fails, monitoring shows no new data, and application logs flood with

HikariPool-1 - Connection is not available, request timed out after 30000ms

or Druid's get connection timeout, activeCount=50, maxActive=50. The core signal is active=maxActive, meaning every connection in the pool is busy and new requests cannot acquire one.

Two Root Causes

The author states there are only two reasons a pool exhausts:

Connections not returned : code opens a connection but forgets to call close(), so the connection stays checked out until the pool saturates.

Connections borrowed too fast : genuine concurrency spike where all connections are actively working, forcing new requests to queue and time out.

Many teams blame the database first, but the article stresses: check for leaks before scaling .

Verification Steps

Step 1: Inspect Database Connections

Run SHOW PROCESSLIST; and examine the Command column. A large number of Sleep connections indicates the application holds connections idle — classic leak evidence.

Step 2: Check Pool Metrics

HikariCP exposes metrics via Spring Boot Actuator:

hikaricp.connections.active   # current active connections
hikaricp.connections.idle     # idle connections
hikaricp.connections.max      # maximum pool size

If active stays equal to max for a long time without dropping, connections are being held and not released.

Fixing Connection Leaks

The most common leak sources are ResultSet, Statement, and Connection objects not closed in finally blocks, especially when exceptions skip the cleanup code.

Correct Pattern: try-with-resources (Java 7+)

try (Connection conn = dataSource.getConnection();
     PreparedStatement stmt = conn.prepareStatement(sql);
     ResultSet rs = stmt.executeQuery()) {
    // process data
} catch (SQLException e) {
    log.error("Query failed", e);
}
// auto-closes all three resources

Error-Prone Pattern: Manual finally

Connection conn = null;
try {
    conn = dataSource.getConnection();
    // business logic
} catch (SQLException e) {
    // handle
} finally {
    conn.close(); // NPE if conn is null
}

Tuning for High Concurrency (No Leaks)

If leaks are ruled out, adjust HikariCP parameters in application.yml:

spring:
  datasource:
    hikari:
      maximum-pool-size: 50          # default 10
      minimum-idle: 10               # min idle connections
      connection-timeout: 30000      # acquire timeout (ms)
      idle-timeout: 600000           # max idle life (10 min)
      max-lifetime: 1800000          # max connection life (30 min)
      leak-detection-threshold: 60000 # leak warning threshold (60 sec)

Key parameters: maximum-pool-size: set via load testing, typically 20–50. connection-timeout: 30s; too short causes false timeouts. leak-detection-threshold: 60s; logs a stack trace when a connection exceeds this age.

When the Database Is Truly Overloaded

If the pool is tuned and leak-free but still saturates, the database itself is the bottleneck. Remedies:

Identify and optimize slow queries that hold connections long.

Add read replicas to offload SELECT traffic.

Introduce caching to reduce direct database hits.

Leak Detection Tools

HikariCP Leak Detection

Enable leak-detection-threshold: 60000. After 60 seconds, HikariCP logs a warning with the creation stack trace of the leaked connection:

WARN [HikariPool-1] - Connection leak detection triggered for connection HikariProxyConnection@123456, stack trace:
  at com.example.service.ReportService.queryReport(ReportService.java:45)
  at ...

This points directly to the line that borrowed the connection and never returned it.

Druid Monitoring Console

Enable spring.datasource.druid.stat-view-servlet.enabled=true to access a real-time dashboard showing pool status, connection hold times, and SQL execution statistics.

Best Practices (避坑指南)

Don't blindly increase maximum-pool-size . Database connection limits are finite; 20–50 is a safe starting range, validated by load tests.

Enable leak detection in production to catch leaks early, not after exhaustion.

Always close connections with try-with-resources ; manual finally blocks are error-prone.

Watch for long transactions . If a transaction calls external APIs, the connection stays locked until commit. Move external calls outside the transaction.

Pair Druid's maxActive with maxWait . maxActive caps connections; maxWait sets acquire timeout. Too short → false kills; too long → poor UX.

Quick Reference

Symptom: active=maxActive sustained → Root Cause: Connection leak → Solution: Verify close() execution

Symptom: active fluctuates, occasional timeouts → Root Cause: Concurrency peak → Solution: Increase maximum-pool-size Symptom: Many Sleep connections → Root Cause: Connections not released → Solution: Enable leak detection, locate stack

Symptom: Pool full + high DB CPU → Root Cause: Slow queries hog connections → Solution: Optimize slow SQL

3-Step Rapid Diagnosis

Read the log: is it active=max (pool full) or timeout (wait expired)?

Run SHOW PROCESSLIST; look for Sleep connections — many means leak.

Search code for unclosed connections, especially in exception paths.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

backend developmentconnection poolperformance tuningHikariCPtry-with-resourcesDruiddatabase troubleshootingconnection leak
Engineer Tang's Implementation Study Notes
Written by

Engineer Tang's Implementation Study Notes

Old Tang | Pseudo-full-stack tech player: writes code without going bald, manages projects without going crazy, delivers without staying up late. No formal tutorials here, only a "slacking-off" practical manual that cures system pain points. Focuses on Shell, SQL, Java, and delivery, turning complexity into simplicity and making efficiency fun.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.