virtual-threads
- 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.
- The Throughput Was Always 115
28 mock APIs. Twelve benchmark scenarios. Two codebases. One number: 115 req/s.
- Designed a Reactive Benchmark. Imperative Won.
Built a reactive benchmark with realistic latency. The imperative rewrite survived memory pressure. Reactive didn't.
- 265 req/s on All Three Runtimes (Until You Add a Memory Limit)
Native image, JVM, and virtual threads all hit 265 req/s. Then the memory limit dropped.
- ExecutorType.VIRTUAL Doesn't Exist
The Config Everyone Writes#micronaut: executors: io: type: VIRTUAL Every tutorial. Every "Micronaut + virtual threads" blog post. Every AI suggestion. This is the obvious config. One property, clean intent. It crashes at startup: No enum constant …
- We Removed Reactor. Nothing Got Slower.
We took the entire reactive stack out. R2DBC, Mono, Flux, Reactor Core, loom-carrier, flatMap with its carefully-tuned concurrency arguments. Replaced it with JDBC, HikariCP, and blocking method calls. Same endpoints. Same Netty HTTP server. Same PostgreSQL. …
- Loom Carrier on a Reactive Stack: 78 MB for Free
"Virtual threads don't help reactive apps." You've heard this. Probably said it. The reasoning is sound: a fully reactive stack — Mono/Flux from HTTP client through R2DBC to Netty — never blocks a platform thread. Virtual threads solve blocking. No blocking, …