Public APIs can receive a large number of requests, sometimes even abusive traffic. Without protection, this can overload your server or database.
A
rate limiter restricts how many requests a client can send within a specific time window. Redis is perfect for this because it is extremely fast and supports atomic operations.
This guide shows how to implement a simple Redis-based rate limiter in Spring Boot.
1. How Rate Limiting Works
The idea is simple:
- Every request increases a counter in Redis.
- The counter has a time-to-live (TTL).
- If the request count exceeds a limit, the request is rejected.
Example:
Limit: 10 requests per minute
Key: rate_limit:192.168.1.1
Redis automatically resets the counter after the TTL expires.
2. Creating a Rate Limiter Service
Create a service that manages request limits.
@Service
public class RedisRateLimiterService {
@Autowired
private RedisTemplate<String, Integer> redisTemplate;
public boolean allowRequest(String key, int limit, Duration window) {
Integer count = redisTemplate.opsForValue().get(key);
if (count == null) {
redisTemplate.opsForValue().set(key, 1, window);
return true;
}
if (count < limit) {
redisTemplate.opsForValue().increment(key);
return true;
}
return false;
}
}
This method checks whether a request is allowed.
3. Applying Rate Limiting in a Controller
Now use the rate limiter in an API endpoint.
@RestController
@RequestMapping("/api")
public class ApiController {
@Autowired
private RedisRateLimiterService rateLimiter;
@GetMapping("/data")
public ResponseEntity<String> getData(HttpServletRequest request) {
String ip = request.getRemoteAddr();
String key = "rate_limit:" + ip;
if (!rateLimiter.allowRequest(key, 10, Duration.ofMinutes(1))) {
return ResponseEntity.status(429)
.body("Too many requests");
}
return ResponseEntity.ok("Request successful");
}
}
If a user sends more than 10 requests per minute, the API returns
HTTP 429.
4. Using User-Based Rate Limits
Instead of IP addresses, you can limit by user ID or API key.
Example key format:
rate_limit:user:123
rate_limit:api_key:abc123
This works well for authenticated APIs.
5. Using Atomic Redis Operations
Redis operations are atomic, which means multiple servers can safely update counters at the same time.
Example increment:
redisTemplate.opsForValue().increment(key);
This ensures accurate request counting even in distributed environments.
6. Sliding Window Rate Limiting (Improved Strategy)
The previous example uses a
fixed window.
A more accurate method is a
sliding window using Redis sorted sets.
Example idea:
Key: rate_limit:user123
Value: request timestamps
Old timestamps are removed automatically, and only recent requests are counted.
This approach prevents sudden bursts at window boundaries.
7. Monitoring Rate Limiting
You should track rate limit activity to detect abuse.
Useful metrics:
- Number of blocked requests
- Top rate-limited IPs
- Requests per endpoint
Spring Boot Actuator can help expose these metrics.
image quote pre code