graalvm
- Your GraalVM Version Is the Other Number
Which GraalVM to build native images with in 2026, what the free edition lacks, and why the image tag shows the JDK version, not GraalVM's.
- The Config I Measured Was Not the Config That Ran
A Spring Boot native image never got its telemetry config file, and optional: kept quiet. Plus a compose run that swapped the app before a load test.
- Same Builder, Different Binary
One GraalVM builder image, one banner on every build log, 18 native binaries. Twelve came out PIE and six didn't, and nobody had touched a linker option.
- The Flag Was Verified. The File Was Never Read.
Spring's process-aot writes its own native-image.properties over yours. A verified GraalVM flag sat in the repo for 43 days and never reached the build.
- Health 200, API 200, Prometheus 000
A GraalVM 25i4 bump made native /prometheus stop answering. The reflection gap was old; a new default turned a missing metric into a hang.
- The Baseline Was the Bug
The JVM platform-thread baseline was measuring virtual threads, and native's famous 8x was dispatch plus double the heap. Matched, the gap is memory.
- Native Image Grew to 734 MB
Five things the benchmark taught me that the documentation didn't mention.
- Eight Connections, Zero Available
Two reactive frameworks hit the same 60 rps wall. The pool said all 8 connections were busy. Postgres said they were idle.
- 16,700 Classes Before Your First Request
Quarkus JVM OOMs at 256 MB while Micronaut and Spring Boot fit. Not heap. Not a leak. It's 86 MB of metaspace that never shrinks.
- Four Bugs That Needed Real Postgres to Exist
A code review found zero bugs. The benchmark found four. Each one required concurrent load against real Postgres to exist.