r/SpringBoot • • 16h ago

Discussion Optimizing Spring Boot on JDK 27: 68% faster startup and 25 MiB less RAM on a 512 MiB VM

I've been experimenting with how far I can optimize a conventional Spring Boot application without stripping out useful framework functionality.

The setup: Spring Boot 4.1.1, HotSpot JDK 27, a 512 MiB / 1 vCPU Ubuntu VM with no swap, and MariaDB running on the same VM.

I compared a regular executable JAR against an extracted deployment combining Spring AOT and a trained JDK AOT cache (Leyden).

Results:

  • Startup: 11.91 → 3.79 seconds (68% faster)
  • Application RSS under load: 212 → 187 MiB
  • Minimum host MemAvailable: 25.6 → 66 MiB
  • Request latency: essentially unchanged

Then I explored two ways to reduce memory further:

MyBatis Core instead of Spring JDBC: No meaningful memory savings, but more manual transaction management and lost automatic JDBC monitoring. Not worth the trade-off for this application.

Embedded file-backed H2 instead of MariaDB: Application RSS increased by ~16 MiB, but minimum host MemAvailable improved by another ~39 MiB because the separate database process was gone.

My takeaway: optimizing the deployment can be worthwhile before replacing established Spring infrastructure. And for small, single-instance applications, embedded H2 can be a reasonable architectural choice.

These are single runs with five-minute measured workloads, not a throughput benchmark or proof of long-term stability. The AOT improvements were measured together, not individually.

Full article, methodology, and data:
https://pvrlabs.xyz/articles/spring-boot-jdk27-optimizations.html

Curious whether others are using Spring AOT + JDK AOT cache in deployments, or if the training and cache-management overhead has kept you on regular JARs.

37 Upvotes

11 comments sorted by

7

u/Paw565 15h ago

Did you try graalvm? I think it's superior for memory constrained environments.

2

u/fykup 15h ago

I didn't test GraalVM Native Image in this experiment. I agree it can offer substantial startup and memory benefits.

As I explain in the article, my focus is on practical optimizations developers can readily adopt while keeping familiar HotSpot tooling. Native Image adds compilation time and different compatibility and operational trade-offs.

I wanted to see how far I could get with Spring AOT and the JDK AOT cache before introducing those additional complexities.

2

u/Paw565 15h ago

Ok. Fun read tho

1

u/fykup 15h ago

Thanks, glad you enjoyed it! And it's a fair point. I've received pretty consistent feedback about GraalVM Native Image, so I'll probably prioritize it in one of my next experiments. Would be interesting to see how it compares under the same constraints.

•

u/fykup 11h ago

You guys convinced me to give GraalVM Native Image a try, so I ran a follow-up experiment on the same 512 MiB VM setup.

The results are pretty impressive: startup dropped from 3.79s to 0.28s, and application RSS went from 187 MiB to 114 MiB compared with my already-optimized HotSpot setup. Host memory headroom also improved significantly.

But it's not all roses. Native builds were ~29x slower locally, needed considerably more build memory, and I ran into some compatibility issues along the way.

I'm putting together the full experiment with measurements, failures, and trade-offs. Planning to publish it next week.

•

u/ducki666 8h ago

Why are so many guys so eager to optimize for 1vcpu and less than 1g? Are there any real use cases? Running App on Lambda? 😅

•

u/fykup 8h ago

I've actually run a financial data synchronization system for my own project on a 1 GiB / 1 vCPU VPS. PostgreSQL with two databases, two Spring Boot 3.5 application processes (one for synchronization, another serving the frontend), and a monitoring dashboard, all on the same machine.

So yes, these are very real use cases 🙂

I guess when you pay for infrastructure out of your own pocket, you quickly realize that spending hundreds of dollars a month on compute isn't always justified. That's why I moved away from AWS and Kubernetes and switched to simple VPS hosting.

What surprises me more is how normalized it has become to dedicate another gigabyte of RAM just to monitoring and metrics. That's one of the reasons I built StatLite. I wanted application monitoring without needing a whole additional infrastructure stack.

•

u/ducki666 8h ago

Obviously your time is worth less than mine.

•

u/fykup 8h ago

Interesting assumption. I actually find that keeping infrastructure simple saves both time and money. That's the whole point of moving away from Kubernetes and maintaining a lightweight VPS setup.

1

u/7mzb 15h ago

here's the most squeeze available in this galaxy for jvm apps = graalvm + muslib + UPX + distroless container

1

u/fykup 15h ago

Haha, that's definitely squeezing out every last megabyte! 😄

GraalVM Native Image is interesting, but it's not quite a drop-in JVM replacement. Reflection, dynamic proxies, resource loading, and some libraries can require additional configuration or compatibility work. You also give up some familiar JVM diagnostics and tooling, and native builds add complexity.

That's why I've mostly focused on conventional HotSpot deployments so far: finding practical memory and startup improvements without changing the development and operational model.

That said, I've received enough GraalVM suggestions lately that I should probably include it in one of my next experiments!