Rate Limiting in Spring WebFlux
Last Updated :
23 Jul, 2025
Rate limiting is a crucial technique to control the amount of incoming traffic to the server. This prevents abuse, ensures fair resource usage, and protects against potential Denial of Service (DOS) attacks. In the Spring WebFlux, rate limiting can be implemented effectively using the Spring Cloud Gateway. This article will guide setting up the rate limiting in the Spring WebFlux application.
Rate limiting restricts the number of requests the client can make to the server within the specified period. In Spring WebFlux, it can be achieved using Spring Cloud Gateway with Redis as the backing store to track the request counts and limits of the Spring application.
Key Components
- Spring Cloud Gateway: The library that provides a simple, yet powerful way to route API requests of the application.
- Redis: An in-memory data structure store that can be used as the database, cache, and message broker.
- KeyResolver: The component that resolves the key for the rate-limiting and is typically based on the client IP or user identity.
Prerequisites:
- Good understanding of the Spring Boot and Spring Reactive.
- Basic understanding of the Rate Limiting concept.
- JDK and IntelliJ Idea setup installed in your local system.
- Maven for building dependency management.
Implementation of Rate Limiting in Spring WebFlux
Step 1: Create a Spring Project
Create a new Spring Boot project using spring Initializr and add the below dependencies.
Dependencies:
- Spring Web Reactive
- Lombok
- Spring DevTools
After creating the project, the folder structure will be like below image in the IDE.
Step 2: Configure the Application Properties
Now, configure the application property of the project by the adding the below properties:
spring.application.name=example-ratelimit
server.port=8081
Step 3: Create the GreetController class
Java
package org.example.exampleratelimit;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@RestController // Annotation to define this class as a RESTful web service controller
@RequestMapping("/greet") // Maps HTTP requests to /greet to methods in this controller
public class GreetingController {
@GetMapping // Annotation to map HTTP GET requests to this method
public Mono<String> greet(ServerWebExchange exchange) {
// Create a Mono that emits a greeting message
return Mono.just("Hello, Welcome to Spring WebFlux with Rate Limiting!")
.doOnSuccess(message -> {
// Add custom headers to the response for rate limiting information
exchange.getResponse().getHeaders().add("X-RateLimit-Limit", "10"); // Maximum allowed requests
exchange.getResponse().getHeaders().add("X-RateLimit-Remaining", ""); // Remaining requests
exchange.getResponse().getHeaders().add("X-RateLimit-Reset", ""); // Time until the rate limit resets
});
}
}
This code defines a Spring WebFlux REST controller that handles HTTP GET requests to the /greet endpoint. It returns a greeting message and adds custom headers to the response for rate limiting information, such as the request limit, remaining requests, and the reset time.
Step 4: Main class
No changes are required in the main class.
Java
package org.example.exampleratelimit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ExampleRatelimitApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleRatelimitApplication.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.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>example-ratelimit</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>example-ratelimit</name>
<description>example-ratelimit</description>
<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 5: Run the application
Now, run the application and it will start at port 8081 of Netty server.
Setup the Gateway Service
Step 1: Create the Spring Project
Create a new Spring Boot project using spring Initializr and add the below dependencies.
Dependencies:
- Spring Web Reactive
- Lombok
- Spring DevTools
- Spring Cloud Gateway
After creating the project, the folder structure will be like below image:
Step 2: Configure the Application Properties
spring:
cloud:
gateway:
routes:
- id: greeting_route
uri: http://localhost:8081
predicates:
- Path=/greet
filters:
- name: RequestRateLimiter
args:
key-resolver: "#{@userKeyResolver}"
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 1
data:
redis:
port: 6379
host: localhost
Step 3: Create the RateLimitingConfig Class
Java
package org.example.ratelimitgateway;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
@Configuration // Indicates that this class contains Spring configuration
public class RateLimitingConfig {
@Bean // Defines a bean for the application context
public KeyResolver userKeyResolver() {
// Resolves the key for rate limiting based on the client's IP address
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
}
This code defines a configuration class for rate limiting in a Spring Cloud Gateway application. It includes a KeyResolver bean that resolves the key for rate limiting based on the client's IP address. The resolved key is used to track and limit requests from individual clients.
Step 4: Main Class
No changes are required in the main class.
Java
package org.example.ratelimitgateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RatelimitGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(RatelimitGatewayApplication.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.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>ratelimit-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ratelimit-gateway</name>
<description>ratelimit-gateway</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</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>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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 5: Run the application
Now run this and it will start at port 8080 in Netty server.
Testing the Application
Note: When the rate limit is exceeded then the server responds with the 429 Too Many Requests status code.
GET http://localhost:8080/greet
Output:
By using Spring Cloud Gateway and Redis, we can easily set up and configure the rate limiting based on the client IP addresses or other criteria.
Explore
Java Enterprise Edition
Multithreading
Concurrency
JDBC (Java Database Connectivity)
Java Frameworks
JUnit