Orbit · Explore

Programming · by Amelia Hughes · 2026-10-11

6 months running Java 25 virtual threads in production — the good, the weird, and the one footgun

Migrated our order-processing service off a traditional thread-pool model to virtual threads on Java 25. Throughput under load genuinely improved and the code got simpler (no more manual thread pool tuning). The footgun: synchronized blocks still pin the carrier thread, and we had a legacy library doing synchronized logging that quietly tanked our concurrency gains for 2 weeks before we found it. Lesson learned — audit every synchronized block before you migrate, don't assume the JVM will save you

0 sparks · 10 comments

Comments

Jiho Lee · 0 likes

the synchronized pinning gotcha got us too, ended up writing a quick bytecode scanner to flag every synchronized block in our dependency tree before the migration, saved a lot of pain

Bianca Santos · 0 likes

would you be willing to share that scanner? sounds genuinely useful for anyone else doing this migration

Sleepy Panda · 0 likes

virtual threads are great until you hit a library that does ThreadLocal in a way that assumes thread reuse, that one bit us hard

Noah Miller · 0 likes

honestly impressed loom finally matured to the point real companies trust it in prod, this was vaporware feeling for SO many years

Pixel Baker · 0 likes

we did the same migration and our main win was just deleting like 400 lines of manual executor service config. simpler code alone was worth it

Grace Parker · 0 likes

curious what your p99 latency looked like before/after, we saw throughput gains but p99 got slightly worse under extreme burst load

Amina Okafor · 0 likes

same actually, p99 under burst got marginally worse for us too, suspect its related to scheduler fairness tradeoffs, still investigating

Ethan Brooks · 0 likes

can confirm synchronized + virtual threads is the new 'works on my machine', found 3 separate pinning issues just last sprint

Angel Reyes · 0 likes

this is why i always tell junior devs to read the migration guide's footguns section twice before touching prod, saves so much pain later

Hugo Martin · 0 likes

not to be that guy but have you tried ReentrantLock instead of synchronized where you control the code? fixes pinning entirely in those spots