Rate Limiting with Redis

7 questions found

What is rate limiting, and why is Redis a good fit for implementing it?

Beginner
Rate limiting restricts how many times a specific action, such as an API call, can happen within a given time period, and Redis is well suited for this because its fast, atomic counter operations and automatic key expiration let you accurately track and enforce these limits with very low latency, even under high traffic.
INCR api_calls:user123
EXPIRE api_calls:user123 60
Real-world example An API gateway limits each customer to one hundred requests per minute, using a Redis counter that increments with every request and automatically resets every sixty seconds thanks to the key's expiration.

Common follow-ups: What happens if the increment and expire commands are not executed atomically together?;How do you choose an appropriate time window for a specific rate limit?

Lua Scripting;Expiration & Eviction

How do you implement a basic fixed window rate limiter using Redis's INCR and EXPIRE commands?

Beginner
You increment a counter key representing the current time window each time a request comes in, and set an expiration on that key only the first time it is created, so the counter automatically resets once the time window passes, letting you reject any request once the counter exceeds your configured limit within that window.
local count = redis.call('incr', KEYS[1])
if count == 1 then
  redis.call('expire', KEYS[1], 60)
end
return count <= 100
Real-world example A login endpoint limits attempts to five per minute per IP address using a simple fixed window counter, automatically resetting the count once each minute passes.

Common follow-ups: What is a known weakness of the fixed window approach near the boundary between two windows?;How do you handle a burst of requests right at the start of a new window?

Lua Scripting;Expiration & Eviction

What is the sliding window log algorithm for rate limiting, and how can it be implemented using a Redis sorted set?

Intermediate
The sliding window log algorithm stores a timestamp for every single request in a sorted set, removes timestamps older than the allowed window before checking the current count, and rejects the request if too many timestamps remain within the current window, providing more accurate rate limiting than a fixed window since it does not have a hard reset boundary that can be gamed.
ZREMRANGEBYSCORE requests:user123 0 (current_time - 60)
ZADD requests:user123 current_time current_time
ZCARD requests:user123
Real-world example A payment API uses a sliding window log to precisely enforce ten requests per minute per customer, correctly preventing a burst of requests that would otherwise slip through right at a fixed window's reset boundary.

Common follow-ups: What is the memory cost of storing a timestamp for every single request?;How does this approach compare in accuracy to a simpler fixed window counter?

Sets & Sorted Sets in Redis;Data Types

What is the token bucket algorithm for rate limiting, and what advantage does it offer over a simple fixed window counter?

Intermediate
The token bucket algorithm maintains a bucket that refills with tokens at a steady rate up to a maximum capacity, with each request consuming one token, allowing short bursts of traffic to be handled smoothly as long as tokens are available, while still enforcing an overall average rate limit over time, unlike a fixed window which can allow a sudden burst right at the window boundary.
-- Simplified token bucket logic using a Lua script
local tokens = tonumber(redis.call('get', KEYS[1]) or capacity)
if tokens > 0 then
  redis.call('decrby', KEYS[1], 1)
  return 1
end
return 0
Real-world example A video streaming service uses a token bucket rate limiter to allow occasional short bursts of requests from a user's device while still maintaining a steady average request rate over time, providing a smoother user experience than a strict fixed window.

Common follow-ups: How do you implement the steady token refill process efficiently in Redis?;When is token bucket a better choice than sliding window log?

Lua Scripting;Redis Performance Tuning & Benchmarking

How would you implement a distributed rate limiter using Redis that works correctly across multiple application servers handling requests for the same user?

Advanced
You centralize all rate limit counting in Redis rather than in each individual application server's local memory, using an atomic Lua script to check and increment the shared counter, ensuring that no matter which specific application server receives a given request, they are all checking against the exact same shared, consistent count for that user.
-- All application servers call the same atomic Lua script
-- against the same shared Redis key for a given user
EVALSHA rate_limit_script_sha 1 'user:123:limit' 100 60
Real-world example A company running dozens of application servers behind a load balancer uses a shared Redis based rate limiter, ensuring a user cannot bypass their rate limit simply by having requests routed to different application servers.

Common follow-ups: What happens to rate limiting accuracy if the Redis instance itself becomes temporarily unavailable?;How do you handle rate limiting during a Redis failover event?

Distributed Locks with Redis;Redis Sentinel & High Availability

How would you design a tiered rate limiting system that applies different limits based on a user's subscription plan?

Advanced
You would store each user's specific limit, either directly with their rate limit key or looked up separately based on their plan, and pass that appropriate limit value into your rate limiting logic, allowing free tier users to have a lower limit while premium users receive a higher limit, all using the same underlying rate limiting mechanism.
-- Look up the user's specific limit based on their plan
local userLimit = plan == 'premium' and 1000 or 100
local count = redis.call('incr', KEYS[1])
return count <= userLimit
Real-world example An API provider offers free tier customers one hundred requests per hour while premium customers receive one thousand, using the same underlying Redis rate limiting logic but with a different limit value applied based on each customer's specific plan.

Common follow-ups: How do you handle a user who upgrades their plan mid billing cycle?;Should different endpoints within the same application have different rate limits?

Lua Scripting;Redis Performance Tuning & Benchmarking

How do you provide helpful feedback to API consumers about their current rate limit status, such as how many requests they have remaining?

Intermediate
You typically include rate limit information in your API response headers, such as the maximum allowed requests, how many remain in the current window, and when the limit will reset, calculated directly from the same Redis counter and expiration data your rate limiter is already using to enforce the limit.
-- Calculate remaining requests and reset time
-- from the same Redis key used for enforcement
TTL api_calls:user123
GET api_calls:user123
Real-world example An API returns headers showing a customer has used forty five of their one hundred allowed requests this minute, with twenty seconds remaining until the limit resets, all calculated directly from the existing rate limiting Redis keys.

Common follow-ups: What standard header names are commonly used for communicating rate limit information?;How do you communicate what happens once a client actually exceeds their limit?

Redis CLI & Basic Commands;Redis Monitoring & Observability