What happens when your batch job goes from “it works on my laptop” to triggering out-of-memory errors and DDoS-ing your own dependencies? In this talk, we’ll walk through the real-world evolution of a high-scale Spring Boot + gRPC workload — from a single-threaded prototype to a concurrency pipeline held together with virtual threads, semaphores, and hard lessons.
You’ll see what happens when parallelStream() backfires, how misused thread pools create bottlenecks, and how rate limiting inside your async tasks can stall your fanout. Through practical examples and code walk-throughs, we’ll explore the trade-offs between different concurrency tools — and why “just making it async” isn’t enough.
Key takeaways:
- Why parallelStream() isn’t always your friend (especially with nested structures or flatMap)
- How to safely mix CompletableFuture, thread pools, and blocking IO
- When to use RateLimiter, Semaphore, or both — and how to protect your dependencies and yourself
- What virtual threads actually solve (and what they don’t)
If you’ve ever added concurrency and made things worse, this talk is for you.