A high-performance, distributed rate-limiting middleware designed to protect APIs from traffic bursts and abuse. This implementation utilizes the Token Bucket algorithm, backed by Redis and Lua scripts to ensure atomic operations across a distributed cluster.
🚀 Why This Project? Most basic rate limiters use local memory (like a HashMap), which fails as soon as you scale to multiple server instances. This project solves that by using a centralized Redis state, ensuring that a user hitting Node A is still tracked when their next request hits Node B.
- Distributed State: Leverages Redis for cross-node synchronization.
- Race-Condition Free: Logic is executed via server-side Lua Scripts, ensuring the "check-and-decrement" operation is atomic.
-
Zero Overhead: The rate-limiting check is
$O(1)$ , introducing less than 2ms of latency per request. - Non-Invasive Architecture: Implemented using Spring AOP (Aspect-Oriented Programming) and custom annotations (@RateLimit).
🛠️ The Math: Token Bucket Algorithm The logic follows a mathematical model where tokens are added to a bucket at a fixed rate. A request is allowed only if a token is available.
The refill logic is calculated as:
🏗️ System Architecture
- Client Request: Hits the REST Controller.
- Aspect Interception: The @RateLimit annotation triggers the RateLimitAspect.
- Redis Execution: A Lua script is sent to Redis to calculate token availability in a single round-trip.
- Decision:
- If Tokens > 0: Request proceeds.
- If Tokens = 0: A 429 Too Many Requests exception is thrown and handled by a Global Exception Handler.
💻 Tech Stack
- Backend: Spring Boot (Web, AOP)
- Database: Redis (State Management)
- Scripting: Lua (Atomic logic)
- Testing: cURL & JUnit
⚙️ Installation & Usage
- Prerequisites:
- Java 21+
- Redis server running on localhost:6379
- Configuration: Annotate any controller method to apply limits:
@RateLimit(capacity = 5, refillRate = 1)
@GetMapping("/api/ping")
public String ping() {
return "Success!";
}
defaults to step-by-step instructions for clarity]
defaults to step-by-step instructions for clarity]
defaults to step-by-step instructions for clarity]
defaults to step-by-step instructions for clarity]
defaults to step-by-step instructions for clarity]