Druid vs HikariCP: Which Java Connection Pool Wins?
The article compares Alibaba’s Druid and Spring Boot’s default HikariCP connection pools, explaining how connection pooling works, presenting benchmark results that show HikariCP’s lower latency and higher TPS, detailing HikariCP’s lock‑free ConcurrentBag and bytecode optimizations, and highlighting Druid’s rich monitoring, SQL firewall and leak detection features to help developers choose the right pool for different scenarios.
Preface
A colleague asked which connection pool is better: Druid or HikariCP. Both are popular open‑source Java connection pools, with Druid coming from Alibaba and HikariCP being the default in Spring Boot 2.x/3.x.
What a Database Connection Pool Does
Creating a new JDBC connection for every request is costly because each connection requires a TCP handshake, authentication, and session setup. A connection pool pre‑creates a set of connections at startup, allowing requests to borrow a connection from the pool and return it after use, thus avoiding repeated creation overhead.
HikariCP Performance
2.1 Simple Performance Test
The following benchmark creates a HikariDataSource with a maximum pool size of 20 and runs 100 concurrent threads, each obtaining a connection and calling isValid(1):
// Simple benchmark for high concurrency
public class ConnectionPoolBenchmark {
@Test
public void testHikari() throws Exception {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test");
config.setUsername("root");
config.setPassword("123456");
config.setMaximumPoolSize(20);
// Enable leak detection (explained later)
config.setLeakDetectionThreshold(5000);
HikariDataSource ds = new HikariDataSource(config);
// 100 threads concurrently acquire connections
ExecutorService executor = Executors.newFixedThreadPool(100);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
executor.submit(() -> {
try (Connection conn = ds.getConnection()) {
// Simulate business logic
conn.isValid(1);
} catch (SQLException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
long end = System.currentTimeMillis();
System.out.println("Total time: " + (end - start) + "ms");
}
}Results show that under 100‑thread concurrency, HikariCP obtains connections with sub‑5 ms latency, consumes little memory, and can sustain over 150 k TPS in the TechEmpower benchmark, whereas Druid achieves 80‑120 k TPS.
2.2 Why HikariCP Is Fast
The core of HikariCP is the lock‑free ConcurrentBag class, which uses a CopyOnWriteArrayList, ThreadLocal, and AtomicInteger to manage connections without global locks. The borrow method first tries the thread‑local cache (no lock) and only falls back to a synchronized shared list when necessary.
public class ConcurrentBag<T> {
// sharedList holds all connections
private final CopyOnWriteArrayList<T> sharedList;
// threadList holds connections used by the current thread
private final ThreadLocal<List<Object>> threadList;
// Number of threads waiting for a connection
private final AtomicInteger waiters;
/**
* Core method to borrow a connection from the pool
*/
public T borrow(long timeout, final TimeUnit timeUnit) throws InterruptedException {
// ① Try ThreadLocal first – completely lock‑free!
List<Object> list = threadList.get();
for (int i = list.size() - 1; i >= 0; i--) {
final T bagEntry = (T) list.remove(i);
// CAS operation, lock‑free state update
if (bagEntry != null && bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {
return bagEntry;
}
}
// ② If ThreadLocal is empty, try sharedList with timeout and synchronizer
// ...
}
}Because most borrow operations succeed in the thread‑local cache, locking is rarely needed, giving HikariCP its speed advantage. Druid, by contrast, uses synchronized structures for both borrow and return, leading to higher contention.
HikariCP also performs bytecode‑level optimizations, such as replacing ArrayList with a custom FastList to reduce boundary‑check overhead.
2.3 Pool Size Golden Rule
Setting maximumPoolSize too large is a common mistake. The optimal pool size follows the formula:
Optimal connections = (CPU cores × 2) + number of disks
For a 4‑core database server, the optimal size is about 9 connections; 10‑20 connections can handle thousands of concurrent requests. Keeping minimumIdle equal to maximumPoolSize avoids unnecessary pool expansion and contraction.
# Recommended HikariCP configuration (production)
spring:
datasource:
hikari:
maximum-pool-size: 20 # set according to the golden formula
minimum-idle: 20 # keep pool size fixed
connection-timeout: 3000 # 3 seconds
idle-timeout: 600000 # 10 minutes
max-lifetime: 1800000 # < wait_timeout of DB
leak-detection-threshold: 60000 # 60 seconds
validation-timeout: 5000 # 5 secondsTwo important notes: max-lifetime must be less than the DB server’s wait_timeout to avoid “Pipe broken” errors. leak-detection-threshold logs the stack trace of the code location that failed to return a connection, aiding debugging.
Druid’s Strengths
While HikariCP excels at raw performance, Druid shines in monitoring and safety.
3.1 Built‑in Monitoring
Druid provides a visual dashboard showing active/idle connections, SQL execution time, row count, and can correlate web requests with database interactions.
Enabling the monitor is as simple as adding a few properties to application.yml and accessing http://localhost:8080/druid to view the dashboard.
# application.yml
spring:
datasource:
druid:
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-username: admin
login-password: 123456
reset-enable: false
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: "*.js,*.css,*.jpg,/druid/*"
session-stat-enable: true
filter:
stat:
enabled: true
db-type: mysql
log-slow-sql: true
slow-sql-millis: 1000
wall:
enabled: true
config:
delete-allow: false
drop-table-allow: false3.2 Leak Detection and Protection
Druid’s leak‑detection settings automatically reclaim abandoned connections and log the stack trace of the offending code.
@Configuration
public class DruidConfig {
@Bean
public DataSource druidDataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("root");
ds.setPassword("123456");
ds.setInitialSize(10);
ds.setMaxActive(100);
ds.setMinIdle(10);
// Core leak‑detection configuration
ds.setRemoveAbandoned(true); // auto‑reclaim leaked connections
ds.setRemoveAbandonedTimeout(180); // 180 s considered a leak
ds.setLogAbandoned(true); // log stack trace
ds.setAbandonWhenOverflow(true); // reclaim when pool is full
// Validation and keep‑alive
ds.setValidationQuery("SELECT 1");
ds.setTestWhileIdle(true);
ds.setTimeBetweenEvictionRunsMillis(60000);
// Enable monitoring and firewall
ds.setFilters("stat,wall");
return ds;
}
}3.3 SQL Firewall
Druid ships with WallFilter, which blocks dangerous statements such as DROP TABLE or DELETE without a WHERE clause, providing an extra layer of protection for compliance‑heavy domains.
// Enable WallFilter
ds.setFilters("stat,wall"); // stat = monitoring, wall = firewall
Map<String, String> wallConfig = new HashMap<>();
wallConfig.put("deleteAllow", "false"); // forbid DELETE
wallConfig.put("dropTableAllow", "false"); // forbid DROP TABLE
wallConfig.put("createTableAllow", "false"); // forbid CREATE TABLE
WallConfig config = new WallConfig(wallConfig);
WallFilter wallFilter = new WallFilter();
wallFilter.setConfig(config);
ds.setProxyFilters(Arrays.asList(wallFilter));Side‑by‑Side Comparison
In summary, the two pools differ on several dimensions:
Design philosophy : HikariCP is a minimalist “sports car” focused on raw speed; Druid is a feature‑rich “SUV” emphasizing monitoring.
Performance : HikariCP typically <5 ms connection acquisition and >150 k TPS; Druid 10‑25 ms and 80‑120 k TPS.
Memory footprint : ~130 KB for HikariCP vs ~2 MB for Druid.
Monitoring : Druid offers a visual dashboard, SQL‑level tracing, and built‑in statistics; HikariCP provides only basic metrics.
SQL firewall : Druid includes WallFilter; HikariCP does not.
Leak detection : Druid can auto‑reclaim and log stack traces; HikariCP logs the stack but does not auto‑reclaim.
Choosing the Right Pool – Practical Guidance
There is no universally “better” pool; the choice depends on the project’s priorities.
When to Pick HikariCP
Microservice or cloud‑native architectures where fast startup and low memory usage matter.
High‑concurrency transaction systems (e.g., flash sales) where every millisecond counts.
New Spring Boot projects that already ship HikariCP by default.
Containerized environments with limited memory.
When to Pick Druid
Enterprise back‑office systems that need SQL audit, performance analysis, and real‑time monitoring.
Financial, medical, or other compliance‑heavy domains requiring SQL firewall and audit trails.
Legacy systems where troubleshooting is frequent; Druid’s dashboard speeds up diagnosis.
Large teams that benefit from a shared visual monitoring platform.
Conclusion
If you prioritize ultimate performance, HikariCP is the “sports car” that accelerates quickly. If you need deep observability, security, and operational safety, Druid is the “SUV” that handles rough terrain with confidence.
If you chase raw speed, choose HikariCP; if you need comprehensive monitoring and protection, choose Druid.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Su San Talks Tech
Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
