Orbit · Explore

Programming · by Kabir Khan · 2026-10-10

Java 25 virtual threads are quietly changing how we write concurrent backend code

Been migrating an old thread-pool-per-request service to virtual threads (Project Loom, stabilized a while back and still improving in Java 25) and the mental model shift is bigger than expected. Blocking code that used to need careful pooling just... works now, and scales to tens of thousands of concurrent connections without the usual thread-starvation headaches. Anyone hit weird edge cases with ThreadLocal, synchronized blocks pinning carrier threads, or monitoring tools that assume platform threads?

0 sparks · 9 comments

Comments

Gentle Sparrow · 0 likes

the synchronized pinning thing bit us hard, had a legacy library using synchronized blocks everywhere and it tanked our throughput untill we found it with async-profiler

Tiago Costa · 0 likes

yeah pinning is the #1 gotcha everyone finds the hard way, JEP 491 in newer releases helps a lot with this specific case though

Léa Bernard · 0 likes

our APM vendor straight up didnt support virtual threads properly for like a year after launch, thread dumps were useless garbage

Amelia Hughes · 0 likes

this is the biggest quality of life improvement to java backend dev since... honestly maybe ever? no more reactive spaghetti just to get concurrency

Faisal Al Saud · 0 likes

switched a spring boot monolith over, gc pressure actualy went down bc we werent allocating massive thread pools anymore. wasnt expecting that

Mateo Cruz · 0 likes

ThreadLocal usage needs auditing hard before you migrate, we had some nasty memory growth from thread locals that assumed thread reuse semantics

Curious Lantern · 0 likes

still think people underestimate how much simpler this makes onboarding juniors, dont have to teach the whole reactive/future composition mental model anymore

Jasmine Cruz · 0 likes

big agree, explaining CompletableFuture chains to new grads was always rough

Urban Panda · 0 likes

we tried it for a cpu bound workload by mistake lol, obviously no benefit there since its all about IO blocking, lesson learned