Introduction
HikariCP is the default JDBC connection pool in Spring Boot. Understanding its configuration parameters is critical for optimal application performance and resource utilization. This guide provides verified information about HikariCP defaults and behaviors based on source code analysis and real-world testing.
Terminology: Spring Boot vs Spring Data JPA
Use "Spring Boot" when discussing:
- Application framework and auto-configuration
- Dependency management and starter dependencies
- HikariCP integration and DataSource configuration
- Overall application architecture
Use "Spring Data JPA" when discussing:
- Repository interfaces and database operations
- Entity management and ORM behavior
- JPA-specific features like
@Entity,@Repository - Hibernate integration
For this blog post about connection pooling: Use "Spring Boot" because:
- HikariCP is configured through Spring Boot auto-configuration
- Connection pool settings are in
spring.datasource.hikari.*namespace - Spring Data JPA is an optional layer that uses the DataSource configured by Spring Boot
The Default Configuration Myth
Common Misconception
"HikariCP 6.x changed defaults to 2 minimum connections and 8 maximum connections."
Reality
HikariCP defaults have remained consistent across versions:
minimumIdle: 10
maximumPoolSize: 10
This applies to:
- HikariCP 5.0.1 (Spring Boot 3.2.0)
- HikariCP 6.3.0 (Spring Boot 3.5.0)
- All other HikariCP versions
Source Code Evidence
// com.zaxxer.hikari.HikariConfig.java
private static final int DEFAULT_POOL_SIZE = 10;
public HikariConfig() {
minIdle = -1; // -1 means use maximumPoolSize
maxPoolSize = DEFAULT_POOL_SIZE; // 10
connectionTimeout = 30000; // 30 seconds
idleTimeout = 600000; // 10 minutes
maxLifetime = 1800000; // 30 minutes
}
When minIdle = -1, HikariCP sets it equal to maxPoolSize during validation, resulting in 10 connections.
Critical Parameters
1. minimumIdle
What it does: Minimum number of idle connections HikariCP maintains in the pool.
Default: 10
Behavior:
- Pool creates 1 connection immediately on initialization
- Background thread fills pool to
minimumIdleover ~500ms - Connections are kept alive even when idle
Configuration:
spring.datasource.hikari.minimum-idle=2
Impact:
Default (10): 10 idle connections always maintained
Configured (2): 2 idle connections maintained, scales up under load
Recommendation: Set to 2-5 for most applications to reduce resource usage.
2. maximumPoolSize
What it does: Maximum number of connections (idle + active) the pool can contain.
Default: 10
Behavior:
- Hard limit on total connections
- Pool will not create more connections than this value
- Requests wait if all connections are active and limit is reached
Configuration:
spring.datasource.hikari.maximum-pool-size=20
Sizing Formula:
connections = ((core_count * 2) + effective_spindle_count)
For typical applications:
- Low traffic: 5-10 connections
- Medium traffic: 10-20 connections
- High traffic: 20-50 connections
Important: Consider your database's max_connections limit.
3. connectionTimeout
What it does: Maximum time (milliseconds) a client will wait for a connection from the pool.
Default: 30000 (30 seconds)
Behavior:
- If no connection available within timeout, throws
SQLException - Does NOT control how long to wait for database connection establishment
- Only controls wait time for getting a connection from the pool
Configuration:
spring.datasource.hikari.connection-timeout=20000
Recommendation:
- Web applications: 20000-30000ms (20-30 seconds)
- Batch jobs: 60000ms+ (1 minute or more)
- Microservices: 10000-20000ms (10-20 seconds)
4. idleTimeout
What it does: Maximum time (milliseconds) a connection can sit idle before being removed from the pool.
Default: 600000 (10 minutes)
Behavior:
- Only applies to connections beyond
minimumIdle - Idle connections are closed after this timeout
- Pool never goes below
minimumIdle - Set to 0 to disable (connections never removed)
Configuration:
spring.datasource.hikari.idle-timeout=300000
Example:
minimumIdle=2, maximumPoolSize=10, idleTimeout=300000 (5 min)
Scenario:
- Normal load: 2 idle connections maintained
- Traffic spike: Pool grows to 8 connections
- After spike: Extra 6 connections idle
- After 5 minutes: Extra 6 connections closed, back to 2
Recommendation:
- Production: 300000-600000ms (5-10 minutes)
- Development: 60000ms (1 minute) for faster cleanup
5. maxLifetime
What it does: Maximum lifetime (milliseconds) of a connection in the pool.
Default: 1800000 (30 minutes)
Behavior:
- Connections are closed and recreated after this time
- Prevents stale connections
- Should be shorter than database/proxy connection timeout
- Applies to all connections (idle and active)
Configuration:
spring.datasource.hikari.max-lifetime=1200000
Critical: Set this several seconds shorter than database wait_timeout:
Database wait_timeout: 600 seconds (10 minutes)
HikariCP maxLifetime: 570000ms (9.5 minutes)
Recommendation:
- With load balancer/proxy: Match proxy timeout minus 30 seconds
- Direct database: 1200000-1800000ms (20-30 minutes)
- Aurora/RDS: Consider RDS Proxy timeout settings
6. initializationFailTimeout
What it does: Controls pool initialization failure behavior.
Default: 1 (millisecond)
Behavior:
- Positive value: Pool initialization fails if first connection cannot be acquired within timeout
- 0 or negative: Pool initialization never fails, connections acquired on-demand
- Does NOT control lazy vs eager initialization with Spring Data JPA
Configuration:
spring.datasource.hikari.initialization-fail-timeout=0
Common Misconception: Setting to 0 achieves "lazy initialization" with 0 startup connections.
Reality: With Spring Data JPA, the pool initializes during EntityManagerFactory creation regardless of this setting.
Recommendation:
- Production: 1 (default) - fail fast on startup issues
- Development: 0 - allow app to start even if database is temporarily unavailable
Spring Boot Integration
Auto-Configuration
Spring Boot automatically configures HikariCP when spring-boot-starter-jdbc or spring-boot-starter-data-jpa is on the classpath:
@Configuration
@ConditionalOnClass(HikariDataSource.class)
static class Hikari {
@Bean
@ConfigurationProperties("spring.datasource.hikari")
HikariDataSource dataSource(...) {
// Creates HikariDataSource with HikariCP defaults
// Properties from application.properties override defaults
}
}
Key Point: Spring Boot does NOT override HikariCP defaults. It uses @ConfigurationProperties binding to apply your configuration.
Configuration Namespace
All HikariCP settings use the spring.datasource.hikari.* prefix:
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.pool-name=MyAppPool
Spring Data JPA Impact
When using spring-boot-starter-data-jpa, the connection pool initializes during application startup:
Initialization Sequence:
- Spring Boot creates
HikariDataSourcebean - Spring Data JPA creates
EntityManagerFactory - Hibernate validates database schema
- This triggers HikariCP pool initialization
- Pool creates 1 connection immediately
- Background thread fills to
minimumIdle
Timeline:
T=0.0s: Application starts
T=0.5s: HikariDataSource created (no connections yet)
T=0.8s: EntityManagerFactory initialization begins
T=0.9s: HikariCP creates 1 connection
T=1.0s: Background thread starts filling to minimumIdle
T=1.5s: Pool reaches minimumIdle connections
T=1.6s: Application ready
Real-World Configuration Examples
Example 1: Microservice (Low Traffic)
# Minimal footprint
spring.datasource.hikari.minimum-idle=1
spring.datasource.hikari.maximum-pool-size=5
spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=1200000
Use case: REST API with occasional database queries, deployed in containers.
Example 2: Standard Web Application
# Balanced configuration
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
Use case: Typical web application with moderate traffic.
Example 3: High-Traffic Application
# Performance-focused
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=50
spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=1200000
spring.datasource.hikari.keepalive-time=120000
Use case: High-traffic application with consistent database load.
Example 4: Behind RDS Proxy
# Optimized for connection pooling proxy
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=570000 # 9.5 min (proxy timeout is 10 min)
Use case: Application using AWS RDS Proxy or similar connection pooling proxy.
Monitoring and Debugging
Enable Debug Logging
logging.level.com.zaxxer.hikari=DEBUG
logging.level.com.zaxxer.hikari.HikariConfig=DEBUG
Output:
DEBUG com.zaxxer.hikari.HikariConfig : HikariPool-1 - configuration:
DEBUG com.zaxxer.hikari.HikariConfig : minimumIdle.....................2
DEBUG com.zaxxer.hikari.HikariConfig : maximumPoolSize.................10
DEBUG com.zaxxer.hikari.pool.HikariPool : Pool stats (total=2/10, idle=2/10, active=0, waiting=0)
Programmatic Monitoring
@Component
public class HikariMonitor {
@Autowired
private HikariDataSource dataSource;
@Scheduled(fixedRate = 60000) // Every minute
public void logPoolStats() {
HikariPoolMXBean pool = dataSource.getHikariPoolMXBean();
log.info("HikariCP Stats - Active: {}, Idle: {}, Total: {}, Waiting: {}",
pool.getActiveConnections(),
pool.getIdleConnections(),
pool.getTotalConnections(),
pool.getThreadsAwaitingConnection());
}
}
JMX Monitoring
spring.datasource.hikari.register-mbeans=true
Access via JConsole/VisualVM:
com.zaxxer.hikari:type=Pool (HikariPool-1)- Metrics: activeConnections, idleConnections, totalConnections, threadsAwaitingConnection
Database-Side Monitoring
PostgreSQL:
SELECT
application_name,
count(*) as connections,
state
FROM pg_stat_activity
WHERE datname = 'your_database'
GROUP BY application_name, state;
MySQL:
SELECT
user,
db,
COUNT(*) as connections
FROM information_schema.processlist
WHERE db = 'your_database'
GROUP BY user, db;
Common Pitfalls and Solutions
Pitfall 1: Relying on Defaults
Problem: Assuming HikariCP defaults are optimal for your application.
Reality: Defaults (10/10) are conservative and may waste resources.
Solution:
# Explicitly configure based on your needs
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
Pitfall 2: Setting maximumPoolSize Too High
Problem: Setting maximum-pool-size=100 thinking more is better.
Reality: Too many connections can:
- Overwhelm the database
- Increase context switching overhead
- Waste memory
- Reduce overall performance
Solution: Use the sizing formula:
connections = ((core_count * 2) + effective_spindle_count)
For a 4-core system: (4 * 2) + 1 = 9 connections
Pitfall 3: Ignoring maxLifetime vs Database Timeout
Problem: Setting max-lifetime longer than database wait_timeout.
Reality: Database closes connections, but HikariCP thinks they're still valid, causing errors.
Solution:
# Database wait_timeout: 600 seconds (10 minutes)
# Set HikariCP maxLifetime shorter:
spring.datasource.hikari.max-lifetime=570000 # 9.5 minutes
Pitfall 4: Confusing initializationFailTimeout with Lazy Loading
Problem: Setting initialization-fail-timeout=0 expecting 0 connections at startup.
Reality: With Spring Data JPA, pool initializes during EntityManagerFactory creation regardless.
Solution: Accept that JPA applications initialize the pool at startup. Focus on optimizing minimumIdle instead.
Pitfall 5: Not Monitoring Pool Exhaustion
Problem: Application hangs under load with no clear error.
Reality: All connections are active, new requests wait for connectionTimeout, then fail.
Solution:
# Enable metrics
spring.datasource.hikari.register-mbeans=true
# Monitor threadsAwaitingConnection
# If consistently > 0, increase maximumPoolSize
Performance Tuning Guide
Step 1: Establish Baseline
Start with recommended defaults:
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
Step 2: Monitor Under Load
Enable monitoring and observe:
- Active connections: Peak concurrent queries
- Threads awaiting: Connection starvation indicator
- Connection acquisition time: Performance indicator
Step 3: Adjust Based on Metrics
If threadsAwaitingConnection > 0 frequently:
# Increase maximum pool size
spring.datasource.hikari.maximum-pool-size=20
If activeConnections rarely exceeds 5:
# Reduce maximum pool size
spring.datasource.hikari.maximum-pool-size=8
If idleConnections consistently high:
# Reduce minimum idle
spring.datasource.hikari.minimum-idle=1
Step 4: Optimize Timeouts
For fast queries (< 100ms):
spring.datasource.hikari.connection-timeout=10000 # 10 seconds
spring.datasource.hikari.idle-timeout=300000 # 5 minutes
For slow queries (> 1s):
spring.datasource.hikari.connection-timeout=60000 # 60 seconds
spring.datasource.hikari.idle-timeout=600000 # 10 minutes
Testing and Verification
Test 1: Verify Defaults
Configuration: None (pure defaults)
Expected Result:
minimumIdle: 10
maximumPoolSize: 10
Total connections: 10
Verification:
# Enable debug logging
echo "logging.level.com.zaxxer.hikari=DEBUG" >> application.properties
# Run application and check logs
mvn spring-boot:run | grep "minimumIdle\|maximumPoolSize"
Test 2: Verify Custom Configuration
Configuration:
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=5
Expected Result:
minimum-idle: 2
maximum-pool-size: 5
Total connections: 2
Verification:
@Component
public class PoolVerifier implements CommandLineRunner {
@Autowired
private HikariDataSource dataSource;
@Override
public void run(String... args) {
System.out.println("minimumIdle: " + dataSource.getMinimumIdle());
System.out.println("maximumPoolSize: " + dataSource.getMaximumPoolSize());
HikariPoolMXBean pool = dataSource.getHikariPoolMXBean();
System.out.println("Total connections: " + pool.getTotalConnections());
}
}
Test 3: Verify Database Connections
PostgreSQL:
SELECT
application_name,
count(*) as connections,
state
FROM pg_stat_activity
WHERE datname = 'your_database'
AND application_name = 'your-app-name'
GROUP BY application_name, state;
Expected: Connection count matches HikariCP totalConnections.
Spring Boot Version Compatibility
| Spring Boot | HikariCP | minimumIdle | maximumPoolSize | Notes |
|---|---|---|---|---|
| 2.7.x | 4.0.x | 10 | 10 | Java 8+ |
| 3.0.x | 5.0.x | 10 | 10 | Java 17+ |
| 3.2.0 | 5.0.1 | 10 | 10 | Java 17+ |
| 3.5.0 | 6.3.0 | 10 | 10 | Java 17+ |
Key Takeaway: Defaults remain consistent across all versions. Configuration syntax is identical.
Migration Guide
Upgrading from Spring Boot 2.x to 3.x
No HikariCP configuration changes required. The defaults and configuration properties remain the same.
What does change:
- Java 17+ required
javax.*→jakarta.*imports for JPA entities- Hibernate 6.x (from 5.x)
HikariCP configuration remains identical:
# Works in both Spring Boot 2.x and 3.x
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
Production Checklist
✅ Explicitly configure pool sizes (don't rely on defaults)
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
✅ Set maxLifetime shorter than database timeout
# Database timeout: 600s → Set HikariCP to 570s
spring.datasource.hikari.max-lifetime=570000
✅ Enable monitoring
spring.datasource.hikari.register-mbeans=true
logging.level.com.zaxxer.hikari=INFO
✅ Configure connection timeout appropriately
spring.datasource.hikari.connection-timeout=20000
✅ Set pool name for identification
spring.datasource.hikari.pool-name=MyAppPool
✅ Test under load before production deployment
✅ Monitor database connection limits
-- PostgreSQL
SHOW max_connections;
-- MySQL
SHOW VARIABLES LIKE 'max_connections';
Troubleshooting
Issue: "Connection is not available, request timed out after 30000ms"
Cause: Pool exhausted, all connections active.
Solutions:
- Increase
maximum-pool-size - Optimize slow queries
- Reduce
connection-timeoutto fail faster - Check for connection leaks
Debug:
logging.level.com.zaxxer.hikari=DEBUG
Look for: Pool stats (total=10/10, idle=0/10, active=10, waiting=5)
Issue: Too many database connections
Cause: minimumIdle too high or too many application instances.
Solutions:
- Reduce
minimum-idle - Reduce
maximum-pool-size - Calculate:
total_connections = instances * maximum-pool-size
Example:
10 instances * 10 max connections = 100 total database connections
Database max_connections = 100 → Problem!
Solution: Reduce to maximum-pool-size=8
10 instances * 8 = 80 connections (20% headroom)
Issue: Stale connections / "Connection reset" errors
Cause: maxLifetime longer than database/proxy timeout.
Solution:
# Set shorter than database timeout
spring.datasource.hikari.max-lifetime=570000 # 9.5 minutes
Issue: Slow application startup
Cause: Pool creating minimumIdle connections at startup.
Solution:
# Reduce minimum idle
spring.datasource.hikari.minimum-idle=1
Trade-off: First few requests may experience slight delay while pool fills.
Advanced Configuration
Connection Validation
# Test connections before use (adds overhead)
spring.datasource.hikari.connection-test-query=SELECT 1
# Validation timeout
spring.datasource.hikari.validation-timeout=5000
Recommendation: Omit connection-test-query - HikariCP uses JDBC4 isValid() by default (faster).
Keepalive
# Prevent connections from being closed by database
spring.datasource.hikari.keepalive-time=120000 # 2 minutes
Use when: Database has aggressive idle connection timeout (< 5 minutes).
Leak Detection
# Warn if connection held longer than threshold
spring.datasource.hikari.leak-detection-threshold=60000 # 1 minute
Use in: Development/staging to find connection leaks.
Warning: Adds overhead, disable in production.
Quick Reference
Minimal Configuration (Recommended)
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
Complete Configuration
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.pool-name=MyAppPool
spring.datasource.hikari.register-mbeans=true
Debug Configuration
logging.level.com.zaxxer.hikari=DEBUG
logging.level.com.zaxxer.hikari.HikariConfig=DEBUG
spring.datasource.hikari.leak-detection-threshold=60000
Conclusion
Key Takeaways:
- HikariCP defaults are 10/10 across all versions - don't assume otherwise
- Spring Boot does not override defaults - explicit configuration required
- Start with minimum-idle=2, maximum-pool-size=10 for most applications
- Monitor and adjust based on actual usage patterns
- Set maxLifetime shorter than database/proxy timeouts
- Use "Spring Boot" when discussing connection pool configuration (not "Spring Data JPA")
For optimal performance: Configure explicitly, monitor actively, and tune based on real-world metrics.
References
Document Status: ✅ Verified with source code, runtime testing, and database monitoring
Last Updated: March 9, 2026
Test Environment: Spring Boot 3.5.0, HikariCP 6.3.0, PostgreSQL 18.1, Java 21