Threading model of Spring WebFlux and Reactor

Last Updated : 23 Jul, 2025

Spring WebFlux is a part of the Spring Framework that supports reactive programming and offers an alternative to Spring MVC for building asynchronous, non-blocking web applications. Reactor is the reactive library behind WebFlux, providing tools and abstractions for working with asynchronous streams. Understanding the threading model of Spring WebFlux and Reactor is crucial for efficiently building scalable applications that handle a large number of concurrent users without blocking threads.

Main Concept

In traditional web frameworks like Spring MVC, each request is handled by a dedicated thread from a thread pool. This model can lead to performance issues as the number of concurrent users increases, potentially exhausting the thread pool and causing delays or failures.

Spring WebFlux, on the other hand, is built on Reactor and follows a different threading model. WebFlux leverages a small number of threads, often as few as one per CPU core, to handle many concurrent requests due to the non-blocking nature of reactive programming.

Reactor's Scheduler

Reactor provides a set of Schedulers that control how tasks are executed on different threads. The commonly used Schedulers in WebFlux are:

  • Schedulers.parallel(): Executes tasks on a parallel thread pool, suitable for CPU-bound operations.
  • Schedulers.elastic(): Creates new threads as needed and reuses idle ones, suitable for blocking operations.
  • Schedulers.single(): Executes tasks on a single reusable thread.
  • Schedulers.immediate(): Executes tasks on the caller's thread.

Event Loop Model

WebFlux uses an event loop model similar to Node.js, where a small number of threads handle I/O events. The Netty or Undertow server, commonly used with WebFlux, runs the event loop that processes I/O events and delegates request processing to the reactive pipeline.

Non-blocking I/O

In WebFlux, I/O operations such as database calls or HTTP requests are non-blocking. Instead of waiting for I/O operations to complete, the thread can continue processing other requests, improving overall throughput.

Prerequisites:

  • Familiarity with reactive programming principles such as the Observer pattern, backpressure, and reactive streams.
  • Basic knowledge of creating and running Spring Boot applications.
  • Basic knowledge of threads and concurrency.

Implementing the Reactive API with Spring WebFlux

Step 1: Create the Spring Reactive Project

Create a new Spring WebFlux project using your preferred IDE (e.g., IntelliJ IDEA) with the following options:

  • Name: spring-webflux-demo
  • Language: Java
  • Type: Maven
  • Packaging: Jar

Click on the Next button.

Project Metadata

Step 2: Add the Dependencies

Add the following dependencies into the spring reactive project.

Dependencies

Project Structure

Once created, the project structure should include standard directories like below:

Project Folder Structure

Step 3: Configure the Application Properties

Add the following property to application.properties file:

spring.application.name=spring-webflux-demo

Step 4: Create the ReactiveService Class

Java
package com.gfg.springwebfluxdemo;

import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

@Service
public class ReactiveService {

    public Mono<String> getData() {
        return Mono.just("Hello, WebFlux!")
                .subscribeOn(Schedulers.boundedElastic());  // Run on an elastic thread pool
    }
}

This service returns a reactive Mono containing a string, using an elastic scheduler for non-blocking execution.

Step 5: Create the ReactiveController Class

Java
package com.gfg.springwebfluxdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
public class ReactiveController {

    @Autowired
    private ReactiveService reactiveService;

    @GetMapping("/reactive")
    public Mono<String> getReactiveData() {
        return reactiveService.getData();
    }
}

This controller maps the /reactive endpoint to the ReactiveService, returning a reactive Mono.

Step 6: Main class

No changes are required in the main class.

Java
package com.gfg.springwebfluxdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringWebfluxDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringWebfluxDemoApplication.class, args);
    }

}

pom.xml file:

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gfg</groupId>
    <artifactId>spring-webflux-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-webflux-demo</name>
    <description>spring-webflux-demo</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Step 7: Run the application

Start the application, which will run on port 8080.

Application Started

Step 8: Testing the Endpoint

Access the endpoint via a GET request:

GET http://localhost:8080/reactive

Output:

Access the endpoint via GET request

This test verifies that the service correctly returns "Hello, WebFlux!"

This project demonstrates the understanding of the threading model in the Spring WebFlux and Reactor while providing the practical example to the reinforce the concepts of the Spring Reactive Application.

Comment

Explore