🔹 Definition
- Connection pooling = reusing DB connections instead of creating a new one for every request.
- Opening a DB connection is expensive (network round-trip, authentication, handshake).
- A pool maintains a set of pre-created, reusable connections → improves performance & scalability.
How It Works
- Application requests a connection → pool provides one.
- After use, .close() returns it to the pool (not physically closed).
- Pool manages idle, active, and max connections.
- If pool is exhausted → requests may block or fail (depending on configuration).
Common Implementations
- HikariCP → default in Spring Boot 2+ (fastest, lightweight).
- Apache DBCP, C3P0, Tomcat JDBC Pool (older but still used).
Basic Flow: Request → Connection Pool → DB → Response
Auto-Configuration (Default: HikariCP)
Spring Boot auto-detects a JDBC driver → configures HikariCP automatically.
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=secret
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# HikariCP specific properties
# Following are optional/advanced properties - HikariCP tuning
spring.datasource.hikari.maximum-pool-size=50
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=20000
Example: Using JdbcTemplate (Auto Pooled)
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<User> findAllUsers() {
return jdbcTemplate.query(
"SELECT * FROM users",
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"))
);
}
}
👉 JdbcTemplate automatically uses pooled connections.
You can also directly request a connection from the pool (not recommended in large apps).
@Autowired
private DataSource dataSource;
public void exampleQuery() throws SQLException {
try (Connection conn = dataSource.getConnection()) { // from pool
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("name"));
}
} // conn.close() → returns to pool
}
1. Driver Detection
- At startup, Spring Boot scans the classpath for available JDBC drivers (e.g., mysql-connector-j, postgresql, etc.).
- If a driver JAR is present, Boot knows it can connect to a database.
- 👉 But this step alone does not create a connection pool.
2. DataSource Auto-Configuration
- HikariCP kicks in only when Spring Boot creates a DataSource bean.
- This happens if either:
- You specify spring.datasource.url (and other properties like username/password) in application.properties or application.yml, or
- You define your own DataSource bean.
- Since HikariCP is the default pooling implementation (when present on the classpath), Boot configures a HikariDataSource.
- At this point, HikariCP initializes the connection pool with the configured settings (minimum idle, maximum pool size, connection timeout, etc.)
Note: HikariCP starts pooling only when a DataSource is actually created. Driver detection enables the possibility, but the pool is initialized during DataSource auto-configuration.
1. Connection Pool Tuning
- Set maximum-pool-size based on DB/server capacity.
- Keep minimum-idle reasonable to avoid warm-up latency.
- Use connectionTimeout carefully (don’t set too high).
2. DB Query Optimization
- Always index frequently queried columns.
- Use LIMIT / OFFSET or keyset pagination.
- Use streaming (fetchSize) for huge datasets.
3. App Architecture
- Stateless services → easier to scale horizontally.
- Multiple instances behind a load balancer.
- Use Kubernetes / Docker for scaling.
4. Asynchronous & Non-blocking
- Use Spring WebFlux (reactive stack) for high-concurrency apps.
- Use @Async, CompletableFuture for background tasks.
5. Caching
- Use Redis / Spring Cache to reduce DB hits.
- Cache hot queries and frequently accessed data.
Aspect | Manual Connection | Connection Pooling (HikariCP) | Scaling for Millions of Requests |
Definition | Each request opens/closes new DB connection | Pre-created, reusable connections | Scaling app + DB + infra |
Performance | Slow | Fast | High with tuning |
Resource Usage | High CPU/Memory overhead | Optimized with max pool size | Optimized with load balancing |
Config in Spring | DriverManager.getConnection() | Auto via spring.datasource.hikari.* | Spring Boot + Cloud infra |
Code Example | DriverManager.getConnection(...) | dataSource.getConnection() | Use Redis, batching, async |
Best For | Small/demo apps | Production-ready apps | Enterprise-scale |
Limitations | Not scalable | Limited by DB + pool tuning | Requires infra + monitoring |
- Always use connection pooling (HikariCP).
- Tune pool size based on CPU cores & DB limits.
- Optimize queries (indexes, batching).
- Use caching (Redis, EhCache).
- Scale horizontally → multiple Spring Boot instances.
- Monitor pool health continuously.
1. Micrometer + Actuator (Built-in)
- Spring Boot auto-integrates HikariCP metrics.
- Add dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
- application.properties:
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.endpoint.metrics.enabled=true
Metrics Available (You will see these info):
- hikaricp.connections → Total number of connections (active + idle) in the pool right now.
- hikaricp.connections.active → Connections currently in use by the application.
- hikaricp.connections.idle → Connections sitting available in the pool, ready to be used.
- hikaricp.connections.pending → Threads waiting because no connection is available (possible bottleneck).
- hikaricp.connections.max → Maximum number of connections the pool is configured to allow.
2. Visualization Options
- Prometheus + Grafana → best for production (industry standard).
- Spring Boot Admin → lightweight monitoring.
- JMX → can view via VisualVM/JConsole.
- APM tools → New Relic, Datadog, Dynatrace (deep insights, $$$).
- Connection Leak Detection:
- HikariCP property leakDetectionThreshold (ms).
- Logs a warning if a connection isn’t closed in time.
- Validation Queries:
- Ensures idle connections are still alive.
- HikariCP uses JDBC isValid() → no need for validationQuery (like older pools).
- Transaction Management with Pooling:
- Connections from pool work seamlessly with Spring’s @Transactional.
- Ensure proper rollback/commit handling to avoid leaks.
- Failover & Resilience:
- Use DB replicas + load balancing.
- Connection pools reconnect automatically on transient DB failures.
- Spring Boot + HikariCP gives you fast, reliable, production-ready connection pooling by default.
- Scaling to millions of requests requires pool tuning, DB optimization, caching, async processing, and continuous monitoring.