Implement Rate Limiting with Spring Cloud Gateway and Redis

This tutorial explains how to restrict client access to specific APIs within a time window using Spring Cloud Gateway and Redis, covering the concept, implementation options, and complete code examples for a Redis‑backed rate limiter.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Implement Rate Limiting with Spring Cloud Gateway and Redis

1 Concept

Through a mechanism, limit the number of times a specific client can access a particular interface within a defined time window; exceeding the limit blocks access until the period expires. Two essential elements: the client identity and the target interface.

Client identity

Target interface

2 Implementation Principle

Two approaches: via gateway (covers all services) or via AOP (applies per service, leads to code duplication).

This article implements the gateway approach. To record how many times a client has accessed an interface within the time window, two methods are possible: JVM‑level (requires custom expiration logic) or Redis (leverages key expiration).

Using Redis, each request decrements a counter; when the count falls below zero, an error is returned. Redis automatically deletes expired keys.

3 Code Implementation

Redis configuration:

spring:
  redis:
    host: localhost
    port: 6379
    password: 123123
    database: 8
    lettuce:
      pool:
        maxActive: 8
        maxIdle: 100
        minIdle: 10
        maxWait: -1

Global filter definition:

@Component
public class BrushProofFilter implements GlobalFilter, Ordered {

  private final ReactiveStringRedisTemplate reactiveStringRedisTemplate;

  public BrushProofFilter(ReactiveStringRedisTemplate reactiveStringRedisTemplate) {
    this.reactiveStringRedisTemplate = reactiveStringRedisTemplate;
  }

  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    // Get client IP
    InetAddress address = exchange.getRequest().getRemoteAddress().getAddress();
    // Get request URI
    String path = exchange.getRequest().getPath().toString();
    // Combine as Redis key
    String key = ("ratelimiter:" + address + ":" + path);
    // Set limit: 10 requests per 30 seconds
    return this.reactiveStringRedisTemplate.opsForValue()
        .setIfAbsent(key, "10", Duration.ofSeconds(30))
        .flatMap(exist -> {
          return this.reactiveStringRedisTemplate.opsForValue().decrement(key);
        })
        .doOnNext(num -> {
          if (num < 0) {
            throw new BrushProofException("You are accessing too fast");
          }
        })
        .then(chain.filter(exchange));
  }

  @Override
  public int getOrder() {
    return -2;
  }
}

Custom exception:

public class BrushProofException extends RuntimeException {
  private static final long serialVersionUID = 1L;
  public BrushProofException(String message) {
    super(message);
  }
}

Custom exception handler:

@Component
public class RatelimiterWebExceptionHandler implements WebExceptionHandler {

  @Override
  public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
    if (ex instanceof RatelimiterException re) {
      ServerHttpResponse response = exchange.getResponse();
      response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
      response.getHeaders().add("Content-Type", "text/html;charset=utf8");
      return response.writeWith(Mono.just(response.bufferFactory().wrap(("You are accessing too fast").getBytes())));
    }
    return Mono.error(ex);
  }
}

Test results (images illustrate the request key and rate limiting behavior).

When the request count exceeds 10, access is blocked.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

spring-bootrate-limitingspring-cloud-gateway
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.