A production-grade, distributed rate limiter built using Spring Boot, Redis, and Lua scripting.
It supports global, per-user, and per-endpoint rate limits with atomic operations, ensuring accuracy and consistency in distributed environments.
✅ Atomic Rate Limiting (Redis + Lua)
✅ Multi-level limits (Global / Endpoint / User)
✅ Dynamic configuration via Admin API
✅ Prometheus metrics support
✅ Docker-ready (Redis container)
✅ Extensible for API gateways and microservices
flowchart TD
A[Client Request] --> B[Spring Boot API]
B --> C{RateLimiterService}
C -->|1️⃣ Global Limit| D[Redis Key: rate_limit:global]
C -->|2️⃣ Endpoint Limit| E[Redis Key: rate_limit:endpoint:/api]
C -->|3️⃣ User Limit| F[Redis Key: rate_limit:user_id_endpoint]
D & E & F --> G[(Redis + Lua Script)]
G -->|Allowed| H[✅ 200 OK]
G -->|Blocked| I[🚫 429 Too Many Requests]
| Layer | Technology |
|---|---|
| Backend | Spring Boot 3.5 |
| Language | Java 17 |
| Cache / Storage | Redis |
| Scripting | Lua |
| Monitoring | Micrometer + Prometheus |
| Containerization | Docker |
| Build Tool | Maven |
git clone https://github.com/sanjaykumars-dev/distributed-rate-limiter.git
cd distributed-rate-limiterdocker run -d --name redis -p 6379:6379 redismvn spring-boot:runTest endpoint limit:
curl "http://localhost:8081/api/limit?userId=sanjay&endpoint=/login"Update configuration dynamically:
curl -X POST "http://localhost:8081/api/admin/ratelimiter/update?type=endpoint&name=/login&window=60&limit=3"✅ Expected behavior
- Allowed → HTTP 200 OK
- Blocked → HTTP 429 Too Many Requests
curl "http://localhost:8081/api/limit?userId=sanjay&endpoint=/login"curl -X POST "http://localhost:8081/api/admin/ratelimiter/update?type=global&window=120&limit=10000"curl -X POST "http://localhost:8081/api/admin/ratelimiter/update?type=endpoint&name=/data&window=60&limit=10"src/main/java/com/sanjay/ratelimiter
├── controller/
│ ├── LimitController.java # Handles user rate limit requests
│ └── RateLimiterConfigController.java # Admin endpoint for dynamic updates
├── service/
│ └── RateLimiterService.java # Core Redis + Lua logic
├── util/
│ └── RateLimiterProperties.java # Maps rate-limit YAML configurations
├── script/
│ └── RateLimiterScript.lua # Atomic Redis Lua script
└── DistributedRateLimiterApplication.java # Spring Boot main classExecuted atomically inside Redis:
ARGV[1] = now
ARGV[2] = window
ARGV[3] = limit
-- Remove entries older than the time window
ZREMRANGEBYSCORE key -inf now-window
-- Count requests within window
local count = ZCARD key
-- If below limit, record the new request
if count < limit then
ZADD key now now
EXPIRE key window
return 1 -- Allowed
else
return 0 -- Blocked
end✅ This ensures atomicity — no race conditions under high concurrency.
- Persist rate-limit configurations in Redis for restart safety
- Add Token Bucket / Leaky Bucket algorithms for burst handling
- Support Redis Cluster / Sentinel for high availability
- Provide full Docker Compose setup (App + Redis + Prometheus + Grafana)
- Integration with API Gateways (Kong / NGINX / Zuul)
Sanjay Kumar S
💼 Developer @ Zoho
🚀 Passionate about scalable backend systems and distributed architectures
This project is licensed under the MIT License © 2025 Sanjay Kumar S You are free to use, modify, and distribute this project for both personal and commercial purposes just keep this license notice in your copies or derivatives.
If you found this project helpful:
- ⭐ Star the repository on GitHub
- 🐞 Report issues or suggest improvements via Issues
- 💬 Share it with your network
- 🤝 Connect with me on LinkedIn