H2 is an excellent embedded database, and its built-in connection pool is a reasonable choice for an application that only uses H2. I wanted to see whether using HikariCP with embedded H2 would introduce a meaningful memory or performance cost.

In a short Linux comparison, HikariCP used about 2 MiB more RSS at idle, while memory under moderate load was comparable. Its observed p95 and p99 latency was slightly lower in both runs. All scheduled requests completed without failures, missed slots, or timeouts. This is a result for one workload, not a general ranking of pools.

What I ran

The application used CoilBase and Avaje Jex, a lightweight Java HTTP framework, with a file-based embedded H2 database. CoilBase is a Java framework I am currently developing at PVR Labs. Reads returned up to 100 rows; writes updated counters and inserted a history record in one transaction. The same application and SQL ran with H2's JdbcConnectionPool and HikariCP 7.0.2. Both pools were capped at four connections; Hikari's minimum idle setting was one. H2 ran in the application process, so its memory is included in RSS.

The Ubuntu 24.04 VM had one vCPU, 512 MiB RAM and no swap. Java ran on JDK 27 with SerialGC, a 16 MiB initial heap and an 80 MiB maximum heap. I ran the pools in A/B/B/A order, starting a fresh JVM and database for each run. Filesystem caches were not reset. After idle and warm-up phases, the moderate phase offered a fixed 30 requests per second for 60 seconds, with four reads for every write. Each moderate phase completed 1,800 of 1,800 requests.

This is a short, lightly contended workload, not a pool saturation test. The results describe embedded H2 in this application and environment; they do not establish how the pools compare with an external database, under heavier contention, or over a longer run.

Memory and latency

RSS includes the whole Java process, not just the pool or heap. The table shows the mean of one-second RSS samples within each phase, and request latency percentiles measured after dispatch. The two runs of each pool remain separate.

Moderate mean RSS: H2 native A1 111.05 MiB and A2 110.85 MiB; HikariCP B1 109.05 MiB and B2 109.80 MiB. The horizontal scale starts at 108 MiB.
Mean process RSS during the moderate phase. Each dot represents one run; the axis starts at 108 MiB.
RunPoolIdle RSS, MiBModerate RSS, MiBp95, msp99, ms
A1H2 native85.30111.056.829.71
B1HikariCP87.98109.055.848.42
B2HikariCP87.85109.806.238.84
A2H2 native86.15110.856.9610.21

Hikari's idle means were about 1.7 to 2.7 MiB above the native observations. Under moderate load, all four means fell between 109.05 and 111.05 MiB. Those process-level measurements do not isolate the pool's own allocation. Hikari's p95 ranged from 5.84 to 6.23 ms, compared with 6.82 to 6.96 ms for the native pool. The corresponding p99 ranges were 8.42 to 8.84 ms and 9.71 to 10.21 ms. Two short runs per pool are not enough to turn these differences into a general speed claim.

Measurement note: After occasional scheduling delays on my actively used development Mac, I moved to a separate Linux host for more reliable tail-latency measurements. Diagnostics there revealed an approximately 43 ms latency tail associated with SSH forwarding; QEMU TCP forwarding eliminated it in the diagnostic fixture. The precise SSH mechanism was not established. The final Linux benchmark had no missed slots or timeouts.

The experiment data and method contain the individual runs and their measurements.

Conclusion

Both pools were reasonable choices for this embedded-H2 application. H2's built-in pool is a perfectly good option for an H2-only application, and these measurements show no meaningful difference that would compel a switch. HikariCP was also lightweight in this test: it used slightly more memory at idle, had comparable moderate-load RSS, and showed slightly lower observed tail latency. The short, lightly contended workload does not establish a general performance advantage or predict results for external databases.

HikariCP is a solid choice when an application uses different JDBC databases and benefits from a consistent pool lifecycle. That is why the latest CoilBase preview already uses it in its Hello example. Its AutoCloseable support also simplified datasource cleanup in CoilBase.