Skip to main content
The Spring Boot Redis Rate Limiter is a lightweight, production-ready library that provides distributed rate limiting using Redis as the backend store. It integrates seamlessly with Spring Boot applications through annotations and auto-configuration.

Architecture

The library follows a modular architecture with clear separation of concerns:

Core components

The library is organized into several key packages, each handling a specific responsibility:

Core interfaces

The core package defines the fundamental abstractions:

RateLimiter

Evaluates whether a request should be allowed based on a key and policy

RateLimitEnforcer

Orchestrates the rate limiting flow and throws exceptions when limits are exceeded

RateLimitContext

Provides invocation context (method, arguments, target class) to resolvers

RateLimitPolicyProvider

Resolves rate limit policies from annotations or external configuration

Redis implementation

The redis package contains the RedisRateLimiter class (redis/RedisRateLimiter.java:19), which implements a fixed-window rate limiting algorithm using Redis atomic operations:
  • Uses INCR to atomically increment request counters
  • Sets TTL to automatically expire window buckets
  • Calculates window boundaries based on current time
  • Supports both fail-open and fail-closed behavior
The fixed-window algorithm divides time into discrete windows. Each window starts at a deterministic timestamp calculated from the current time and window duration.

Key resolution

The key package provides strategies for determining which Redis key (bucket) to charge:
  • RateLimitKeyResolver: Interface for custom key resolution strategies
  • DefaultRateLimitKeyResolver (key/DefaultRateLimitKeyResolver.java:11): Default implementation that combines scope, class name, and method name

Configuration

The config package handles Spring Boot integration:
  • RateLimiterProperties (config/RateLimiterProperties.java:9): Externalized configuration via application.properties
  • RateLimiterAutoConfiguration: Auto-configures all beans when Redis is available

How it works

When you annotate a method with @RateLimit, here’s what happens:
1

Annotation processing

Spring AOP intercepts the method call via RateLimitAspect
2

Context creation

A RateLimitContext is created with method details and arguments
3

Key resolution

The RateLimitKeyResolver generates a unique key (e.g., global:com.example.ApiController#getData)
4

Policy resolution

The RateLimitPolicyProvider extracts the policy from the annotation (limit, duration, scope)
5

Rate limit evaluation

The RedisRateLimiter checks if the request should be allowed:
  • Calculates the current window boundary
  • Increments the Redis counter for this window
  • Compares count against the limit
6

Decision enforcement

If allowed, the method executes normally. If denied, a RateLimitExceededException is thrown

Request lifecycle example

Here’s a complete example of how a rate-limited request flows through the system:
@RateLimit(limit = 10, duration = 60, scope = "user")
public ApiResponse getData(@RequestParam String userId) {
    return apiService.fetchData(userId);
}
The AOP aspect intercepts the call before the method body executes.
The DefaultRateLimitKeyResolver generates a key like:
user:com.example.ApiController#getData
The user prefix comes from the scope attribute.
For a 60-second window at timestamp 1,678,900,825,000 ms:
windowStart = 1,678,900,825,000 - (1,678,900,825,000 % 60,000)
            = 1,678,900,820,000
This ensures all requests in the same minute use the same window.
The limiter executes:
INCR ratelimiter:user:com.example.ApiController#getData:1678900820000
EXPIRE ratelimiter:user:com.example.ApiController#getData:1678900820000 61
The TTL is set to 61 seconds (60 + 1 second safety buffer).
If the counter is ≤ 10, the request is allowed. Otherwise, a RateLimitExceededException is thrown with retry information.

Design principles

The library is built on several key principles:

Framework-agnostic core

Core interfaces don’t depend on Spring Web, making them usable in any context (servlets, reactive, gRPC)

Extensibility

You can provide custom implementations of RateLimitKeyResolver, RateLimitPolicyProvider, or even RateLimiter

Observability

Built-in Micrometer metrics integration for monitoring rate limit decisions

Fault tolerance

Configurable fail-open behavior ensures your application stays available even if Redis is down
The library uses Spring Boot’s auto-configuration, so you only need to add the dependency and configure Redis. All beans are created automatically.

Next steps

Rate limiting algorithm

Deep dive into the fixed-window algorithm and Redis operations

Key resolution

Learn how keys are generated and how to customize resolution strategies

Fail-open vs fail-closed

Understand fault tolerance strategies when Redis is unavailable

Build docs developers (and LLMs) love