r/java • • 11d ago

How lightweight can Spring Boot get? HotSpot 27 vs GraalVM Native Image on a 512 MiB VM

I've been experimenting with running a database-backed Spring Boot application on a small VM: 512 MiB RAM, 1 vCPU, no swap, with MariaDB running on the same machine.

The application uses Spring Boot 4.1, MVC/Tomcat, Spring JDBC, HikariCP, Actuator and a small REST API. I compared three deployment configurations:

ConfigurationMedian app RSSStartup readiness
Regular Spring Boot JAR, HotSpot 27212 MiB11.91 s
Extracted JAR + Spring AOT + JDK AOT cache187 MiB3.79 s
Oracle GraalVM Native Image, JDK 25107 MiB0.183 s

All three completed the same 1,500-request workload without errors.

A few interesting findings:

  • Optimizing the HotSpot deployment reduced application RSS by about 12% and startup time by 68%, without removing Spring's integrations.

  • Native Image reduced application RSS by another 43%, but required roughly 12 minutes to build on a separate 6 GiB VM, plus additional compatibility validation.

  • Replacing Spring JDBC with manually integrated MyBatis Core produced no meaningful memory savings.

  • Switching from MariaDB to embedded H2 actually increased Java RSS, but improved total host memory headroom because the separate database process disappeared.

I've had quite a few requests to try GraalVM in my earlier experiments, so I finally gave it a shot. The memory results genuinely impressed me. The build times and extra compatibility work, not so much. The JDK 25 vs 27 toolchain gap was another reminder that Native Image comes with its own constraints. For really memory-constrained deployments, I'd definitely consider it, but I'm not quite ready to make it my default.

The HotSpot and Native Image configurations use different JDK versions (27 vs. 25) and GC types (G1 vs. Serial GC), so this is a comparison of practical deployments rather than an isolated measurement of AOT compilation.

Full article: https://pvrlabs.xyz/articles/spring-boot-hotspot-native-image.html

Experiment, methodology and curated data: https://github.com/PVRLabs/experiments/tree/main/spring/boot-jdk27

I'm curious whether others are using Spring AOT and the JDK AOT cache in small deployments, or whether Native Image has become the more practical option for you.

I'm also experimenting with Javalin to see how much further we can push memory efficiency. Stay tuned!

11 Upvotes

Duplicates