The Problem
AdventureTube is a chain of microservice calls:
Client → Gateway → Auth Service → Member Service → PostgreSQL
→ Geospatial Service → MongoDB / Kafka
Every arrow is I/O wait. In traditional Spring MVC, each waiting request holds a thread hostage doing nothing.
Traditional (Spring MVC) vs Reactive (WebFlux)
| Spring MVC | Spring WebFlux | |
|---|---|---|
| Thread pool | ~200 Tomcat threads | ~4 Netty event loop threads |
| During I/O wait | Thread blocked, wasted | Thread released, serves others |
| 50 concurrent users | Fine | Fine |
| 500 concurrent users | Starts queuing | Still fine (2-3x throughput) |
| 5000+ concurrent users | Thread starvation, timeouts | Still stable (10x+ throughput) |
Core Concept
The pipeline is paused, not the thread.
Every reactive operator (flatMap, delayUntil, filterWhen) works this way — the pipeline pauses, the thread goes back to serve other requests, and when the async result arrives, the pipeline resumes on whatever thread is available.
Reactive Operator Patterns
| Sync (plain value) | Async (Mono/Flux) | Purpose |
|---|---|---|
.map() |
.flatMap() |
Transform element |
.filter() |
.filterWhen() |
Keep/discard element |
.doOnNext() |
.delayUntil() |
Side effect before continuing |
defaultIfEmpty(value) |
switchIfEmpty(Mono.defer(...)) |
Fallback when empty |
Rule: if the lambda returns a Mono/Publisher, use the async variant — otherwise the Mono sits as a dead object, unsubscribed and wrapped.
The Price We Pay
- Different coding style — all code must live inside the reactive pipeline
- Variables can’t be shared between reactive and non-reactive code
- Blocking calls (
passwordEncoder.matches(),verifyGoogleIdToken()) must be offloaded toSchedulers.boundedElastic()viaMono.fromCallable() .block()is forbidden on Netty event loop — it causes thread starvation
Why It’s Worth It for AdventureTube
- Auth service waits on member service (network I/O)
- Member service waits on PostgreSQL (database I/O)
- Geospatial service waits on MongoDB and Kafka (I/O)
- Lots of waiting = lots of idle threads in MVC = exactly where reactive shines
- Same hardware handles many more concurrent users
