Why this matters
- Connection pool exhaustion is a top production failure mode — every request waiting for a connection times out simultaneously.
- Pool sizing directly affects throughput and database load — too few connections starve requests, too many overwhelm the database.
- HikariCP is the fastest pool available for Java; Boot configures it automatically when a DataSource starter is present.
Default configuration
Boot auto-configures HikariCP with sensible defaults:
spring:
datasource:
url: jdbc:postgresql://127.0.0.1:5432/bookstore
username: bookstore
password: ${DB_PASSWORD}
hikari:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
pool-name: BookStorePool
No extra dependency needed — spring-boot-starter-data-jpa includes HikariCP.
Key HikariCP settings
maximum-pool-size— Maximum concurrent connections. Default 10.minimum-idle— Connections kept warm when idle. Default equals max pool size.connection-timeout— Milliseconds to wait for a connection before throwing exception. Default 30s.idle-timeout— How long an idle connection stays in the pool. Default 10 minutes.max-lifetime— Maximum age of a connection before retirement. Default 30 minutes.
Pool sizing formula
A widely used guideline:
connections = (core_count * 2) + effective_spindle_count
For a BookStore API on a 4-core server with SSD:
connections = (4 * 2) + 1 = 9
Set maximum-pool-size: 10. Adjust based on monitoring, not theory.
Critical rule: Total connections across all app instances must not exceed the database's max_connections. With 3 BookStore pods at 10 connections each, you need at least 30 available on PostgreSQL.
Monitoring pool health
Enable HikariCP metrics via Actuator:
management:
endpoints:
web:
exposure:
include: health,metrics
metrics:
enable:
hikaricp: true
Key metrics:
| Metric | Healthy | Problem |
|---|---|---|
| hikaricp.connections.active | Below max | At max = pool exhausted |
| hikaricp.connections.pending | 0 | > 0 = requests waiting |
| hikaricp.connections.timeout | 0 | > 0 = timeouts occurring |
| hikaricp.connections.creation | Stable | Spiking = connection churn |
hikaricp.connections.active
HealthyBelow maxProblemAt max = pool exhaustedhikaricp.connections.pending
Healthy0Problem> 0 = requests waitinghikaricp.connections.timeout
Healthy0Problem> 0 = timeouts occurringhikaricp.connections.creation
HealthyStableProblemSpiking = connection churn
Connection leak detection
spring:
datasource:
hikari:
leak-detection-threshold: 60000
Logs a warning if a connection is held longer than 60 seconds — usually means a transaction was not closed or a connection was not returned to the pool.
Tuning for BookStore workloads
Read-heavy catalog API:
spring:
datasource:
hikari:
maximum-pool-size: 15
minimum-idle: 5
connection-timeout: 5000
Write-heavy order processing:
spring:
datasource:
hikari:
maximum-pool-size: 8
connection-timeout: 10000
Fewer connections for write workloads because transactions hold connections longer.
Read replicas
Route read-only queries to a replica:
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.writer")
public DataSource writerDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.reader")
public DataSource readerDataSource() {
return DataSourceBuilder.create().build();
}
}
Each pool needs its own sizing — reader pool can be larger since reads are faster.
Validating connections
spring:
datasource:
hikari:
connection-test-query: SELECT 1
validation-timeout: 3000
HikariCP validates connections before handing them out. The default connection-test-query works for PostgreSQL; H2 and MySQL may need explicit configuration.
Quick recall
Everything you need if you only revisit this box.
- HikariCP is the default connection pool in Spring Boot — no extra dependency required.
maximum-pool-sizecontrols concurrent connections; default is 10.- Size pools with
(cores * 2) + 1and adjust based on Actuator metrics. - Total connections across all instances must stay below the database limit.
leak-detection-thresholdwarns when connections are held too long.- Monitor
connections.pending— non-zero means requests are waiting for connections.
Test yourself
Answer these before moving on — recall is what makes it stick.