Integrate in 5 Minutes
Add distributed rate limiting to a Spring Boot service with Redis state and optional MongoDB overrides.
What this gives you
You get four algorithms (Token Bucket, Leaky Bucket, Fixed Counter, Sliding Window), per-IP + per-endpoint + per-tier configuration, atomic Redis state via Lua, and optional persistent overrides stored in MongoDB.
Request flow
The filter intercepts each request, resolves configuration from MongoDB and YAML, executes the chosen Redis Lua script, and returns a decision with headers.
Prerequisites
- Java 21
- Spring Boot 4.x
- Redis (local or managed)
- MongoDB (optional but recommended for runtime overrides)
If you already have a Spring Boot service, you keep it and add the rate limiter module.
1) Run dependencies
Start Redis and MongoDB locally.
# Redis
redis-server
# MongoDB (default)
mongodIf you use containers instead, just keep the connection strings for the next step.
2) Configure application.yaml
Add the rate-limit section and your Redis/Mongo settings. This example uses a Token Bucket fallback and a per-endpoint config with user tiers.
spring:
data:
mongodb:
uri: mongodb://admin:password@localhost:27017/rate_limiter_db
authentication-database: admin
redis:
host: localhost
port: 6379
rate-limit:
fallback:
algorithm: TOKEN_BUCKET
capacity: 3
refillRate: 1
endpoints:
- path: /api/test
user-tiers:
free:
algorithm: TOKEN_BUCKET
capacity: 5
refillRate: 0
premium:
algorithm: LEAKY_BUCKET
capacity: 5
flowRate: 1
redis:
key-prefix: "rate-limit"
ttl: 600000
security:
enabled: true
trusted-proxies:
- 127.0.0.1
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16The fallback block defines the default algorithm when no endpoint match exists. The endpoints list defines per-path rules. Each tier under user-tiers can pick a different algorithm and parameters. The Redis TTL determines how long a key survives without traffic; keep it long enough to avoid churn but short enough to avoid stale keys.
If you misconfigure the algorithm parameters, the service returns 400 Bad Request from the config endpoints or logs a validation error during startup. Fix the values and restart.
3) Run the service
./mvnw spring-boot:run4) Hit a rate-limited endpoint
curl -i http://localhost:8080/api/testYou should see these headers in the response:
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 4
X-RateLimit-ResetOn: 1713005400000X-RateLimit-ResetOn is a Unix timestamp in milliseconds. When X-RateLimit-Remaining reaches 0, the next request returns 429 Too Many Requests until that time.
5) Add a persistent override (optional)
Store a per-IP + endpoint + tier override in MongoDB.
curl -X POST http://localhost:8080/api/config/v2 \
-H "Content-Type: application/json" \
-d '{
"ip": "192.168.1.100",
"endpoint": "/api/test",
"userTier": "premium",
"method": "GET",
"algorithm": "TOKEN_BUCKET",
"parameters": {
"capacity": 100,
"refillRate": 10
}
}'This override has the highest priority. The next request from that IP to that endpoint uses the MongoDB config instead of the YAML defaults. If the IP or endpoint does not match, the YAML configuration still applies.
If you send an invalid payload, the service returns 400 Bad Request. Validate the algorithm name and required fields, then retry. If MongoDB is down, you will get a 503 and no override is stored.
What to verify
Confirm that:
X-RateLimit-*headers appear on rate-limited endpoints.429 Too Many Requestsappears once you exceed the limit.- A MongoDB override changes behavior for the matching IP + endpoint + tier.
Request processing flow
flowchart LR
A[HTTP Request] --> B[RateFilter]
B --> C[RateLimitManager]
C --> D{Config Resolution}
D -->|MongoDB| E[Mongo Config]
D -->|YAML| F[YAML Config]
D -->|Fallback| G[Fallback]
C --> H[Redis Lua Script]
H --> I[Decision + Headers]