Rate Limiting with Redis: INCR+EXPIRE and Sliding Window
Fast recall
Quick revision
Core answer
Ability to implement a production-grade distributed rate limiter and awareness of the atomicity requirement and fixed-window boundary burst problem.
Not making INCR+EXPIRE atomic — a process crash between the two commands leaves counters without expiry, effectively blocking the key forever.
Discuss the token bucket or leaky bucket algorithms as alternatives, and mention that Spring Cloud Gateway has built-in Redis rate limiting using the token bucket algorithm.
Interview-ready guide
Interview answer
Rate limiting with Redis is a classic use case because Redis's atomic operations make counter increments safe under concurrent requests from multiple application instances — something in-memory counters can't handle in a distributed deployment.
Fixed window with INCR
- The simple approach:
INCR ip:192.168.1.1:2024-01:16:30increments a counter for this IP in this minute;EXPIREsets the TTL to 60 seconds so the counter resets automatically INCRis atomic — no two concurrent requests can read and write the counter simultaneously without both their increments being recorded- The limitation: fixed windows allow bursting at the window boundary — a client can send 100 requests at 11:59 and 100 requests at 12:00, totaling 200 in a 2-second window even though the limit is 100 per minute
Sliding window with Sorted Set
ZADD requests ip:192.168.1.1 timestamp requestIdadds the request timestamp as the score;ZREMRANGEBYSCOREremoves entries older than the window;ZCARDcounts remaining entries- This gives a true sliding window — the count reflects requests in the last N seconds from now, not from the start of the current minute period; no boundary burst is possible
- Slightly more expensive than INCR: three commands vs one, wrapped in a Lua script for atomicity
Token bucket with Lua script
- The most accurate rate limiting model — each client has a bucket of tokens that refills at a fixed rate; each request consumes one token; if the bucket is empty, the request is rejected
- Implement in a Lua script (
EVAL) to make the read-compute-write atomic in Redis; or use the Bucket4j library which integrates with Redis for Spring Boot applications
Bucket4j with a Redis backend is the recommended production approach for Spring Boot — it provides token bucket semantics, configures via Spring Cloud Gateway, and handles the Lua atomicity automatically.
Rate Limiting with Redis: INCR+EXPIRE and Sliding Window
Direct Answer
The simplest Redis rate limiter uses INCR to count requests per time window and EXPIRE to reset the counter, but this fixed-window approach allows bursts at window boundaries. A sliding window log stores request timestamps in a Sorted Set and counts entries in the last N seconds, providing smooth limiting. For production, Lua scripts make these operations atomic, preventing race conditions between INCR and EXPIRE or ZADD and ZREMRANGEBYSCORE.
Common Mistakes & Pitfalls
Not making INCR+EXPIRE atomic — a process crash between the two commands leaves counters without expiry, effectively blocking the key forever.
Check your understanding
Answer these without looking back at the article.
- What is the difference between the token bucket and leaky bucket rate limiting algorithms?
- How would you implement per-IP rate limiting across multiple application instances?
- What are the memory implications of the sliding window ZSet approach at high request volumes?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.