A backend infrastructure middleware built with Spring Boot that sits in front of any API to throttle traffic, prevent brute-force attacks, and track usage metrics in real time.
Incoming Request → [Spring Boot Filter] → [Redis Lua Script Check] ↓ Blocked? YES → 429 Response + Async MySQL Log NO → Pass to Controller
- Java 21 + Spring Boot 4.0.7 - Core framework
- Redis - Atomic rate limiting using Lua Scripts
- MySQL + Spring Data JPA - Violation audit logging
- Lombok - Boilerplate elimination
Why Redis? Rate limit checks happen on every request. MySQL would be too slow. Redis handles this in under 1ms.
Why Lua Scripts? INCR and EXPIRE must run atomically. Without Lua, two simultaneous requests can both read count=9, both increment, and both get allowed - exceeding the limit. Lua scripts are atomic in Redis.
Why @Async for logging? MySQL writes are slower than Redis reads. Logging violations asynchronously means the 429 response is returned immediately while the log is written in a background thread - no latency added to the blocked request.
Sliding Window counter using Redis INCR + EXPIRE: -Each IP gets a Redis key with a 60-second TTL -Every request increments the counter atomically -Request beyond the limit receive HTTP 429 -Counter auto-resets when TTL expires
Prerequisites: Java 21, Maven, Redis, MySQL
- Clone the repo
- Create MySQL database:
CREATE DATABASE ratelimiter;- Configure credentials in
application.properties - Run:
mvn spring-boot:run- Test rate limiting:
for i in {1..15}; do curl -s -o /dev/null -w "%{http_code}\n"
http://localhost:8080/api/data; done- View dashboard:
http://localhost:8080/index.html
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/data |
Test endpoint (rate limited) |
| POST | /api/submit |
Test endpoint (rate limited) |
| GET | /dashboard/stats |
Overall violation stats |
| GET | /dashboard/violations |
Recent 100 violations |
| GET | /dashboard/stats/{ip} |
Stats for specific IP |