Backend
Stop Slamming Downstream Services: Singleflight Request Coalescing with Java Virtual Threads
Machine coding Master DEV Community
5 views
Stop Slamming Downstream Services: Singleflight Request Coalescing with Java Virtual Threads
Virtual threads solved your JVM I/O bottlenecks, but downstream internal services are now on fire because 50,000 concurrent threads are fetching the exact same cache miss simultaneously. You do not need distributed locks or larger database instances; you need the Singleflight request coalescing pattern inside your JVM.
Why Most Developers Get This Wrong
Reaching for distributed locking: Slapping Redisson or Redis locks over hot cache misses adds unnecessary network hops and operational latency for what is fundamentally an in-process duplicate query problem.
Blocking with synchronized blocks: Using coarse ReentrantLock or synchronized guards pinned carrier threads in early Loom setups and destroys virtual thread scalability across high-throughput services.
Relying purely on TTL caches: When a hot Redis or Caffeine key expires under 20k RPS, raw uncoordinated reads trigger immediate thundering herds across downstream gRPC/REST endpoints.
The Right Way
Suppress duplicate concurrent calls locally by routing identical in-flight keys to a single downstream execution using lock-free coordination.
Use a ConcurrentHashMap to register in-flight CompletableFuture instances keyed by query identity.
The first virtual thread registers the promise and triggers the downstream RPC, while subsequent threads simply wait on the shared future.
Leverage CompletableFuture.join()—virtual threads unmount cleanly from OS carrier threads while awaiting the result.
Automatically evict keys in a finally block or completion callback so future requests trigger fresh executions.
Show Me The Code
Here is an idiomatic, lock-free Singleflight implementation using standard Java concurrency utilities:
public class Singleflight<K, V> {
private final ConcurrentHashMap<K, CompletableFuture<V>> inFlight = new ConcurrentHashMap<>();
public V execute(K key, Supplier<V> task) {
return inFlight.computeIfAbsent(key, k -> {
var future = new CompletableFuture<V>();
Thread.ofVirtual().start(() -> {
try { future.complete(task.get()); }
catch (Throwable ex) { future.completeExceptionally(ex); }
finally { inFlight.remove(k); }
});
return future;
}).join();
}
}
Key Takeaways
Protect your downstream: Virtual threads can absorb massive ingress spikes; without in-JVM coalescing, that traffic acts as a self-inflicted DDoS against internal dependencies.
Lock-free coordination wins: Combining ConcurrentHashMap.computeIfAbsent() with CompletableFuture eliminates thread contention while keeping memory overhead negligible.
Clean up immediately: Always evict keys in finally blocks to avoid memory leaks and prevent transient downstream exceptions from permanently poisoning future callers.
I built javalld.com while prepping for senior roles — complete LLD problems with execution traces, not just theory.
Read original: https://dev.to/machinecodingmaster/stop-slamming-downstream-services-singleflight-request-coalescing-with-java-virtual-threads-1m2o
← Previous
One rounding, not many: why a provably-fair verifier must match the server bit for bit
Next →
Monitoring Jetson CPU, GPU, Temperature and Power from a Flutter Robot Dashboard
Related
Should Your Thread Keep the JVM Alive?
Backend
6
Dev.to (EN Zone)
Monitoring Jetson CPU, GPU, Temperature and Power from a Flutter Robot Dashboard
Backend
5
DEV Community
Nothing could start without the dependency we had filed as optional
Backend
7
DEV Community
What Is Web Development? A Beginner's Guide 2026
Backend
6
Dev.to (EN Zone)
Comments0
No comments yet — be the first