Spring WebFlux and Reactive Programming Explained

Advanced
9 min read· Backend & Databases

Spring WebFlux is the reactive, non-blocking alternative to Spring MVC. Instead of assigning one thread per request and blocking it during I/O, WebFlux runs on a small event loop and represents results as asynchronous streams — Mono (0 or 1 value) and Flux (0 to many). When work is waiting on I/O, the thread is freed to serve others, so a few threads handle enormous concurrency. The trade-off is a steeper mental model and the need for non-blocking libraries end to end.

Think of reactive as a waiter who never waits at the kitchen

In a classic restaurant, each waiter (thread) takes an order and stands at the kitchen until the dish is ready — idle but occupied. A reactive waiter drops the order, immediately serves other tables, and is notified when any dish is ready to deliver. A handful of these waiters serve a packed restaurant because none of them ever stands still waiting. But every station must play along — one slow, blocking chef stalls the whole system.

Step by Step

1 / 5

Key Concepts

Mono vs Flux

Both are reactive publishers from Project Reactor. Mono emits zero or one item (a single lookup); Flux emits zero to many (a stream or list). Operators build pipelines over them.

Non-blocking I/O

The thread issues an I/O request and moves on, being notified when the result is ready — rather than sleeping until it completes. This is what lets few threads serve many requests.

Backpressure

A mechanism where the consumer tells the producer how many items it can accept, preventing a fast source from flooding a slow sink — a defining feature of Reactive Streams.

WebFlux vs Spring MVC

MVC is blocking, thread-per-request, and simpler. WebFlux is non-blocking and scales to high concurrency with few threads, but requires reactive libraries and a different debugging style throughout.

Key Facts

  • Reactive code only pays off when it is non-blocking end to end; mixing a blocking JDBC call into an event loop erases the benefit and can freeze the server.
  • With Java 21 virtual threads, plain blocking Spring MVC now scales to very high concurrency too — often removing the main reason teams chose WebFlux.
  • Never call block() on an event-loop thread; it defeats the model and can deadlock.

Real-World Applications

Streaming and high-fan-out gateways

An API gateway that forwards to many downstream services, or an endpoint streaming server-sent events to thousands of clients, benefits from WebFlux non-blocking concurrency and backpressure.

Real-time data feeds

A Flux backed by a reactive data source can push live updates (prices, notifications) to clients as they occur, composing filters and transformations declaratively.

Frequently Asked Questions

What is the difference between Mono and Flux?

Mono is a reactive publisher that emits at most one item (or an error/empty) — ideal for a single result like findById. Flux emits zero to many items — ideal for lists or streams. Both are lazy and only execute when subscribed.

When should I use Spring WebFlux over Spring MVC?

Choose WebFlux for very high concurrency with mostly I/O-bound work, streaming responses, or when you need backpressure — and when your whole stack can be non-blocking. For most CRUD apps, Spring MVC (especially with Java 21 virtual threads) is simpler and sufficient.

Do virtual threads make reactive programming obsolete?

For many I/O-bound services, virtual threads deliver similar scalability with simple blocking code, removing the main motivation for reactive. Reactive still shines for streaming, composing async data flows, and fine-grained backpressure.

What is backpressure in reactive streams?

It is flow control: the consumer signals how many items it is ready to receive so a fast producer cannot overwhelm it. Reactive Streams build this in, letting the system stay stable under load instead of buffering unboundedly or dropping data.

Related Topics