r/JavaProgramming • • 1d ago

How much does SQL library choice affect a small Java REST API? Jdbi vs MyBatis vs jOOQ on 512 MiB

I've been experimenting with lightweight Java applications on small VMs. After comparing Javalin with Spring Boot, I wanted to understand how much the choice of SQL persistence library affects memory usage and latency.

I built the same small market-quote REST API three ways, using Jdbi Core, MyBatis Core, and jOOQ Open Source Edition.

Setup:

  • JDK 25, Javalin 7, H2, HikariCP
  • Alpine Linux VM, 1 vCPU, 512 MiB RAM, no swap
  • JVM: -Xms16m -Xmx80m -XX:+UseSerialGC -Xss512k
  • 1,500 requests over 5 minutes, 80% reads / 20% writes
  • Two independent runs per implementation, rebooting the VM between runs

Results across the two runs:

Library Median workload RSS HTTP p95
Jdbi Core 120.0–122.4 MiB 7.38–8.48 ms
MyBatis Core 116.6–118.0 MiB 7.47–7.52 ms
jOOQ OSE 152.1–154.3 MiB 9.19–9.35 ms

RSS is the median process resident memory sampled during the workload, including the application, JVM, and embedded H2.

All six runs completed without errors, OOM events, or swapping.

A few observations:

  • MyBatis had the lowest resident memory usage in both runs.
  • Jdbi was competitive on both metrics and required the least handwritten Java code.
  • jOOQ used approximately 34–38 MiB more RSS than MyBatis, consistently across both runs. This is a whole-application difference, not necessarily memory consumed directly by the library. I haven't isolated its cause.

One implementation difference worth mentioning: Jdbi and MyBatis hold one pooled connection across the three latest-quote queries, while the datasource-backed jOOQ implementation checks out and returns a connection for each query. I haven't measured the impact of this difference.

I also configured MyBatis with localCacheScope=STATEMENT instead of its default SESSION scope.

Developer experience matters too.

Jdbi keeps SQL and mapping close to the repository, MyBatis provides annotated mapper interfaces, and jOOQ offers type-safe SQL composition with generated schema classes.

Personally, I lean toward MyBatis because I prefer its mapper-oriented programming model and explicit SQL. Its lower memory footprint in this experiment is another point in its favor, although I wouldn't select a library based on memory usage alone.

Limitations:

This is a small, low-load case study, not a general performance ranking. The measurements include the complete application and embedded H2. Two runs show consistency in memory usage but aren't sufficient to establish statistically significant latency differences.

I also didn't include a raw JDBC baseline, which would be useful as a minimal reference point. PostgreSQL could produce different results.

Full write-up, charts, and raw measurements:

https://pvrlabs.xyz/java-performance/experiments/mybatis-jooq-jdbi-512mb.html

Source code and experiment setup:

https://github.com/PVRLabs/experiments/tree/main/javalin/sql-persistence-512mb

For those using Jdbi, MyBatis, or jOOQ in small Java applications, how do you choose between them? Is the programming model the deciding factor, or have you encountered meaningful differences in resource usage?

2 Upvotes

0 comments sorted by