WebFlux vs Spring MVC — when does each make sense? — Cracked Java
// Spring Framework & Spring Boot · Reactive — WebFlux, Reactor
SeniorSystem DesignBig Tech

WebFlux vs Spring MVC — when does each make sense?

Spring MVC is blocking and thread-per-request; WebFlux is non-blocking and runs on a small event loop. Neither is universally "better" — the choice is driven by your I/O profile and how reactive your dependencies are. The honest senior answer rejects "WebFlux is faster" and reaches for nuance.

How each handles a request

Spring MVC (Servlet stack) assigns one thread to a request for its entire lifetime. While that thread waits on a database or downstream call, it's parked — consuming a thread and its stack memory. Concurrency is capped by the thread pool size; thousands of slow concurrent requests mean thousands of threads (or queuing/timeouts).

WebFlux (Reactor + Netty) runs on a few event-loop threads (roughly one per CPU core). A request that hits I/O releases the thread immediately and resumes via callback when data is ready. A handful of threads multiplex thousands of connections — as long as nothing blocks them.

// MVC: blocking, thread held until DB returns
@GetMapping("/u/{id}") User get(@PathVariable Long id) { return repo.findById(id); }

// WebFlux: non-blocking, thread freed during the DB call
@GetMapping("/u/{id}") Mono<User> get(@PathVariable Long id) { return repo.findById(id); }

When WebFlux wins

  • High concurrency, I/O-bound workloads: API gateways, fan-out aggregation of many downstream calls, lots of slow/idle connections.
  • Streaming: server-sent events, large or infinite responses where you want backpressure and bounded memory.
  • You can be reactive end-to-end (R2DBC, WebClient, reactive security).

When MVC wins

  • CPU-bound work — an event loop gives you nothing when the bottleneck is computation, not waiting.
  • You depend on blocking libraries (JDBC/JPA, blocking SDKs). Wrapping them on a bounded elastic scheduler claws back blocking but adds complexity and erases most of the benefit.
  • Simplicity and debuggability: imperative code, readable stack traces, mature tooling, the whole team already knows it. The reactive learning curve and "stack traces from hell" are real costs.

Mark your status