ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Redis Lua Simple Rate Limiter

Redis Lua

Goal -- WPM

Ready
Exercise Algorithm Area
1local function isAllowed(key, limit, window_seconds)
2-- Implements a simple fixed window rate limiter.
3-- Args:
4-- key: A unique identifier for the entity being rate-limited (e.g., user ID, IP address).
5-- limit: The maximum number of requests allowed within the window.
6-- window_seconds: The duration of the window in seconds.
7-- Returns:
8-- 1 if the request is allowed, 0 otherwise.
9
10if key == nil or limit == nil or window_seconds == nil then
11return redis.error_reply('Invalid arguments: key, limit, and window_seconds must be provided.')
12end
13
14local counter_key = 'rate_limit:' .. key
15local current_count = redis.call('GET', counter_key)
16
17if current_count == nil then
18-- First request in this window
19redis.call('SET', counter_key, 1)
20redis.call('EXPIRE', counter_key, window_seconds)
21return 1
22else
23current_count = tonumber(current_count)
24if current_count >= limit then
25-- Exceeded limit
26return 0
27else
28-- Increment count and check if it's still within limit
29local new_count = redis.call('INCR', counter_key)
30if new_count > limit then
31-- If incrementing pushed it over, return 0, but don't reset expiry
32-- The EXPIRE command will handle the reset when the window ends.
33return 0
34else
35-- Ensure the key has an expiry, in case it was set without one initially
36-- (though our initial SET should handle this, this is a safeguard)
37if redis.call('TTL', counter_key) < 0 then
38redis.call('EXPIRE', counter_key, window_seconds)
39end
40return 1
41end
42end
43end
44end
45
46-- Example usage:
47-- local user_id = 'user123'
48-- local request_limit = 10
49-- local window_duration = 60 -- 60 seconds
50-- local allowed = isAllowed(user_id, request_limit, window_duration)
51-- if allowed == 1 then
52-- print('Request allowed.')
53-- else
54-- print('Request denied: Rate limit exceeded.')
55-- end
Algorithm description viewbox

Redis Lua Simple Rate Limiter

Algorithm description:

This Redis Lua script implements a basic fixed window rate limiter. It tracks the number of requests made by a specific identifier (like a user ID or IP) within a defined time window. If the number of requests exceeds a predefined limit for that window, subsequent requests are denied until the window resets. This is commonly used to protect APIs from abuse and ensure fair usage.

Algorithm explanation:

The `isAllowed` function takes a `key`, `limit`, and `window_seconds`. It uses a Redis key prefixed with 'rate_limit:' to store the request count for the given `key`. If the counter key doesn't exist, it's the first request in the window; the script sets the count to 1, sets an expiry for the window, and returns 1 (allowed). If the counter exists, it checks if the current count exceeds the `limit`. If so, it returns 0 (denied). Otherwise, it increments the counter using `INCR`. If the incremented count is still within the limit, it returns 1. A safeguard `TTL` check ensures the expiry is set if it was somehow missing. The time complexity is O(1) due to Redis's constant-time operations. Space complexity is O(1) per unique `key` used.

Pseudocode:

FUNCTION isAllowed(key, limit, window_seconds):
  counter_key = 'rate_limit:' + key
  current_count = Redis.GET(counter_key)

  IF current_count IS null THEN
    Redis.SET(counter_key, 1)
    Redis.EXPIRE(counter_key, window_seconds)
    RETURN 1
  ELSE
    current_count = TO_NUMBER(current_count)
    IF current_count >= limit THEN
      RETURN 0
    ELSE
      new_count = Redis.INCR(counter_key)
      IF new_count > limit THEN
        RETURN 0
      ELSE
        IF Redis.TTL(counter_key) < 0 THEN
          Redis.EXPIRE(counter_key, window_seconds)
        END IF
        RETURN 1
      END IF
    END IF
  END IF
END FUNCTION