Backend Development 5 min read

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:

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

Global filter definition:

<code>@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;
  }
}
</code>

Custom exception:

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

Custom exception handler:

<code>@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);
  }
}
</code>

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

When the request count exceeds 10, access is blocked.

JavaRedisrate limitingSpring Cloud Gatewayspring-boot
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

login 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.