HikariCP
Spring Boot
Logging
Database Connection Pooling
Java

Logging HikariCP Spring boot

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

HikariCP is the default connection pool in Spring Boot. To enable HikariCP logging, set the com.zaxxer.hikari logger to DEBUG in your application.properties or application.yml. This exposes connection acquisition times, pool statistics (active, idle, waiting connections), leak detection warnings, and connection lifecycle events. Monitoring these logs is essential for diagnosing slow database queries, connection leaks, and pool exhaustion issues.

Basic Logging Configuration

application.properties

properties
1# Enable HikariCP debug logging
2logging.level.com.zaxxer.hikari=DEBUG
3logging.level.com.zaxxer.hikari.HikariConfig=DEBUG
4
5# For detailed pool statistics
6logging.level.com.zaxxer.hikari.pool.HikariPool=DEBUG

application.yml

yaml
1logging:
2  level:
3    com.zaxxer.hikari: DEBUG
4    com.zaxxer.hikari.HikariConfig: DEBUG
5    com.zaxxer.hikari.pool.HikariPool: DEBUG

What the Logs Show

At DEBUG level, HikariCP logs:

 
DEBUG HikariPool - HikariPool-1 - Pool stats (total=10, active=3, idle=7, waiting=0)
DEBUG HikariPool - HikariPool-1 - Added connection conn5
DEBUG HikariPool - HikariPool-1 - Timeout failure stats (total=10, active=10, idle=0, waiting=5)
Log EntryMeaning
total=10Total connections in the pool
active=3Connections currently in use
idle=7Connections available for use
waiting=0Threads waiting for a connection
Added connectionNew connection was created
Timeout failureThread could not get a connection in time

Pool Configuration

properties
1# application.properties
2spring.datasource.hikari.maximum-pool-size=20
3spring.datasource.hikari.minimum-idle=5
4spring.datasource.hikari.connection-timeout=30000
5spring.datasource.hikari.idle-timeout=600000
6spring.datasource.hikari.max-lifetime=1800000
7spring.datasource.hikari.pool-name=MyAppPool
yaml
1# application.yml
2spring:
3  datasource:
4    hikari:
5      maximum-pool-size: 20
6      minimum-idle: 5
7      connection-timeout: 30000    # 30 seconds
8      idle-timeout: 600000         # 10 minutes
9      max-lifetime: 1800000        # 30 minutes
10      pool-name: MyAppPool

Setting pool-name makes logs easier to identify when multiple pools exist.

Leak Detection

HikariCP can detect connections that are borrowed but not returned:

properties
# Warn if a connection is held for more than 30 seconds
spring.datasource.hikari.leak-detection-threshold=30000
yaml
1spring:
2  datasource:
3    hikari:
4      leak-detection-threshold: 30000  # 30 seconds

When a leak is detected, HikariCP logs a stack trace showing where the connection was acquired:

 
1WARN  HikariPool - Connection leak detection triggered for conn7 on thread http-nio-8080-exec-3,
2stack trace follows
3java.lang.Exception: Apparent connection leak detected
4    at com.example.UserRepository.findAll(UserRepository.java:25)
5    at com.example.UserService.getUsers(UserService.java:18)
6    ...

This stack trace shows exactly which code acquired the connection but did not return it.

Monitoring with JMX

Enable JMX to expose pool metrics programmatically:

properties
spring.datasource.hikari.register-mbeans=true
java
1// Access pool metrics programmatically
2import com.zaxxer.hikari.HikariDataSource;
3import com.zaxxer.hikari.HikariPoolMXBean;
4
5@RestController
6public class PoolMonitorController {
7
8    private final HikariDataSource dataSource;
9
10    public PoolMonitorController(DataSource dataSource) {
11        this.dataSource = (HikariDataSource) dataSource;
12    }
13
14    @GetMapping("/pool-stats")
15    public Map<String, Integer> getPoolStats() {
16        HikariPoolMXBean pool = dataSource.getHikariPoolMXBean();
17        return Map.of(
18            "activeConnections", pool.getActiveConnections(),
19            "idleConnections", pool.getIdleConnections(),
20            "totalConnections", pool.getTotalConnections(),
21            "threadsAwaitingConnection", pool.getThreadsAwaitingConnection()
22        );
23    }
24}

Spring Boot Actuator Integration

xml
1<dependency>
2    <groupId>org.springframework.boot</groupId>
3    <artifactId>spring-boot-starter-actuator</artifactId>
4</dependency>
properties
management.endpoints.web.exposure.include=health,metrics
management.endpoint.health.show-details=always

Access pool metrics at:

bash
1# Health check includes pool status
2curl http://localhost:8080/actuator/health
3
4# HikariCP-specific metrics
5curl http://localhost:8080/actuator/metrics/hikaricp.connections.active
6curl http://localhost:8080/actuator/metrics/hikaricp.connections.idle
7curl http://localhost:8080/actuator/metrics/hikaricp.connections.pending
8curl http://localhost:8080/actuator/metrics/hikaricp.connections.timeout
9curl http://localhost:8080/actuator/metrics/hikaricp.connections.usage

Micrometer/Prometheus Integration

properties
# Expose Prometheus endpoint
management.endpoints.web.exposure.include=prometheus
promql
1# Grafana queries for HikariCP monitoring
2hikaricp_connections_active{pool="MyAppPool"}
3hikaricp_connections_idle{pool="MyAppPool"}
4hikaricp_connections_pending{pool="MyAppPool"}
5rate(hikaricp_connections_timeout_total{pool="MyAppPool"}[5m])
6hikaricp_connections_usage_seconds_sum / hikaricp_connections_usage_seconds_count

Logging SQL Queries Alongside Pool Logs

properties
1# Log SQL statements
2logging.level.org.springframework.jdbc.core=DEBUG
3logging.level.org.hibernate.SQL=DEBUG
4
5# Log SQL parameter values
6logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
7
8# Combined with HikariCP logs
9logging.level.com.zaxxer.hikari=DEBUG

Common Pitfalls

  • Setting pool size too high: More connections is not always better. Each connection consumes memory on both the application and database. Start with maximum-pool-size = (2 * CPU cores) + number_of_disks and tune based on load testing.
  • Not enabling leak detection in development: Without leak-detection-threshold, connections held indefinitely (e.g., from missing @Transactional or unclosed resources) silently exhaust the pool. Set it to 30-60 seconds in development.
  • Confusing connection timeout with query timeout: connection-timeout is how long to wait for a connection from the pool. Query timeout (how long a SQL query can run) is configured separately via spring.jpa.properties.jakarta.persistence.query.timeout.
  • Logging at TRACE level in production: HikariCP TRACE logging is extremely verbose and impacts performance. Use DEBUG for troubleshooting and INFO for production.
  • Not monitoring threadsAwaitingConnection: A non-zero waiting count means the pool is undersized or connections are held too long. This is the earliest indicator of pool exhaustion, appearing before timeout errors.

Summary

  • Set logging.level.com.zaxxer.hikari=DEBUG to enable HikariCP connection pool logging
  • Enable leak detection with spring.datasource.hikari.leak-detection-threshold=30000 to find unreturned connections
  • Use Spring Boot Actuator metrics (hikaricp.connections.*) for runtime monitoring
  • Key metrics to watch: active connections, idle connections, threads awaiting connection, and timeout count
  • Set pool-name for clear log identification, especially with multiple data sources

Course illustration
Course illustration

All Rights Reserved.