Demystifying the Spring WebFlux (Why and How)
In modern Java development, we constantly hear buzzwords like Reactive Programming and Spring WebFlux. It promises a non-blocking…
Demystifying the Spring WebFlux (Why and How)

Demystifying the Spring WebFlux
In modern Java development, we constantly hear buzzwords like Reactive Programming and Spring WebFlux. It promises a non-blocking, asynchronous model that can handle thousands of concurrent requests with ease.
But what exactly is WebFlux all about? And more importantly, why do we need it in the first place? Let’s dive in and find out.
Why Do We Need WebFlux ?
Well, for years we have been using Spring Web MVC as the de facto standard for developing Java enterprise applications, and traditionally it uses the concept of a one-thread-per-request model, which runs well in traditional applications handling hundreds of requests per second.
In traditional Spring web applications, we use Tomcat as the default server. Tomcat uses a thread-per-request model, where each incoming request is handled by a dedicated thread, which is simple and easy.
By default, Tomcat’s thread pool size is 200, which means a traditional Spring application can handle 200 concurrent requests at a time.
Let’s assume:
- Each request takes 400 ms to complete.
- But as we know most CRUD based applications the CPU is fast and
- Most of the time is spent waiting for a database/IO (external API) response (typical in CRUD applications).
In this scenario:
- All 200 threads may be waiting for the database.
- New incoming requests must wait in the queue.
- As traffic grows (e.g., 500 RPS), latency and response time increase.
- If the database slows down (say from 200 ms to 400 ms), performance degrades further.
Can we design something better 🤓
Consider this breakdown for a typical request:
- 20 ms CPU processing
- 200 ms waiting for DB
- 20 ms final processing
Total = 240 ms per request
👉 The thread is idle for most of this time.
What if we could reuse threads while they are waiting 😎?
That is the core idea behind WebFlux and reactive programming.
The Idea of WebFlux and Reactive Programming
Spring WebFlux is built on Netty’s event-loop + async I/O model.
In contrast to tomcat Netty runs on a small number of threads called EventLoop threads, typically:
No Of threads= No Of Cores * 2
Rather than hundreds of threads, WebFlux typically runs with a small number of threads (for example, ~32).
And requests are processed through a reactive pipeline not on traditional sync way.
So how does Netty handle 1000’s of Concurrent requests with so limited threads 🤔
Let’s find out
When a request arrives:
- Netty assigns it to an event-loop thread.
- The request performs initial CPU work (~20 ms).
- When a DB call is made:
- The thread is released immediately.
- Netty registers a callback.
- When the DB response arrives:
- The callback is triggered.
- Processing resumes (possibly on a different thread).
✅ A thread is not bound to a single request ✅ Threads are reused efficiently ✅ Much higher concurrency with fewer threads ✅ Lower memory consumption

Netty Event Loop
So, we now know Spring WebFlux works on a smaller number of threads and optimizes the flow by using callbacks instead of binding a single thread to complete a request. But the most important question is…
HOW NETTY pause the execution of thread and resume when the response return from an I/O (DB, External API) response.
What Really Happens During “Pause and Resume”?
Maybe it call the Thread.sleep() and then wait for response but that approach block the thread itself so this is not the way forward.
In WebFlux, a request does not literally pause like a sleeping Java thread.
Instead:
- Work is divided into stages.
- When a stage needs I/O:
- WebFlux registers a callback.
- Control returns to the event loop.
- When data is ready:
- The next stage is triggered
👉 This is continuation via callbacks, not thread blocking.
What Happens During I/O?
When a DB call is made:
- The call is initiated asynchronously.
- The event-loop thread is released immediately.
That thread can now handle:
- Other HTTP requests
- Socket read/write events
- Other reactive pipelines
📌 The pipeline is waiting for a signal, not holding a thread.
How WebFlux Remembers What to Do Next ?
WebFlux internally used Project Reactor and this stores the continuation inside:
- Subscriber (do not worry will explain later)
- Operators (map, flatMap, etc.)
- Internal state machines
Conceptually:
“When data arrives, call the next operator.”
The continuation is represented by:
- Function references
- Operator chain state
- Reactor Context
When Data Returns
When DB/network data arrives:
- The reactive driver emits an event
- Reactor triggers:
onNext(result)
onComplete()
This is the resume phase.
⚠️ Important: It may resume on a different thread and that is the best part because no single thread is bind to a single request.
OK that is nice theory Subscriber, Operators 😑 What the hell are all these
Well the reactive programming works on traditional Design Pattern the Pub-Sub model
Think of it like this:
- ✅ Publisher produces data (asynchronously)
- ✅ Subscriber consumes data (when ready)
- ✅ Data flows only when requested → Backpressure ( will look into this in detail later)
Spring WebFlux uses Project Reactor, which implements Reactive Streams.
Don’t worry let’s look at a typical Spring Rest Request flow and understands how it is working
Consider this controller:
@GetMapping("/users/{id}")
public Mono<User> getUser(@PathVariable String id) {
return userService.findUser(id);
}
Step-by-Step Flow
1️⃣ Netty Receives the Request
Thread name example:
reactor-http-nio-*
Spring WebFlux creates a reactive pipeline and subscribes to it.
2️⃣ Your Mono<User> Is a Publisher
Your controller returns a Mono<User>.
Spring treats it as:
“This is a Publisher. I will subscribe to it.”
i.e it is publishing the User data I should subscribe it to it and get the data
3️⃣ WebFlux Creates a Subscriber
Spring creates an internal ResponseSubscriber whose job is to:
- Take the User
- Serialize it to JSON
- Write it to the HTTP response
4️⃣ Subscription Handshake
Publisher calls:
subscriber.onSubscribe(subscription);
Now the Subscriber controls demand:
subscription.request(1);
For Mono, only 1 item is requested.
📌 Key difference: Subscriber controls the flow.
5️⃣ Publisher Emits Data
When the DB call completes:
subscriber.onNext(user);
subscriber.onComplete();
WebFlux then:
- Converts User → JSON
- Writes the response
- Completes the HTTP request

Request flow for Weblfux
So that’s how a webFlux request flow end to end.
With this, we come to the end of the first part of the series. In the next part, we will take a deep dive into WebFlux and understand what Project Reactor is, how WebFlux uses it, and explore the main components of WebFlux — Mono, Flux, and reactive operators.
메타데이터
- post_id
- f7b0b0705a37
- slug
- demystifying-the-spring-webflux-why-and-how-f7b0b0705a37
- url
- https://medium.com/@write2farrukhmasroor/demystifying-the-spring-webflux-why-and-how-f7b0b0705a37
- canonical_url
- https://medium.com/@write2farrukhmasroor/demystifying-the-spring-webflux-why-and-how-f7b0b0705a37
- author_url
- https://medium.com/@write2farrukhmasroor
- status
- ok
- fetched_at
- 2026-08-17 16:17:32