RateGuard is a production-ready, distributed API rate-limiting service built using Spring Boot, Redis, and Lua scripting.
It demonstrates how modern backend systems enforce request limits reliably under high concurrency and horizontal scaling.
- Sliding window rate limiting (not fixed window)
- Distributed enforcement using Redis
- Atomic rate-limit checks using Redis Lua scripts
- IP-based rate limiting (proxy-aware)
- Dynamic rule resolution (pluggable policy engine)
- Fail-open strategy on Redis failure
- Cloud-deployed (Railway)
Most rate limiters you see online:
- Use in-memory counters ❌
- Break under multiple instances ❌
- Are inconsistent under concurrency ❌
RateGuard solves all of these by using:
- Redis Sorted Sets (ZSETs)
- Lua scripts for atomic operations
- A clean separation of concerns
This mirrors how real systems (API gateways, CDNs, SaaS backends) work.
- Client
- ↓
- Spring Boot Filter
- ↓
- RateLimiter Interface
- ↓
- RedisSlidingWindowRateLimiter
- ↓
- Redis (Lua Script)
| Component | Responsibility |
|---|---|
RateLimitFilter |
Intercepts incoming HTTP requests |
RateLimiter |
Abstraction for rate-limit strategies |
RedisSlidingWindowRateLimiter |
Distributed rate-limit logic |
RateLimitRuleResolver |
Determines limits per request |
| Redis + Lua | Atomic, consistent enforcement |
For each request:
- Remove timestamps older than the window
- Count remaining requests
- Reject if count ≥ limit
- Insert current timestamp
- Set expiry
This avoids burst problems common in fixed-window approaches.
- 5 requests per 10 seconds per IP
This rule is resolved dynamically via RateLimitRuleResolver.
In production environments behind load balancers or reverse proxies:
- Client IP is extracted from
X-Forwarded-For - Fallback to
getRemoteAddr()for local usage
This ensures correctness both locally and in cloud deployments.
- Java 17+
- Spring Boot 3.x
- Spring Web
- Spring Data Redis (Lettuce)
- Redis
- Lua scripting
- Maven
- Railway (deployment)
- Java 17+
- Maven
- Redis (local or Docker)
docker run -d -p 6379:6379 redis:7
#run the application
mvn spring-boot:run
#health endpoint
curl http://localhost:8080/health
#protected endpoint
for i in {1..7}; do curl http://localhost:8080/test; done
- This project is also deployed on Railway with Redis as a managed service: https://rateguard-production.up.railway.app/test