python / expert
Snippet
Sliding Window Rate Limiting Middleware with Atomic Redis Lua Scripts
This Django middleware implements a precise sliding window rate limiter against Redis. Utilizing an inline Lua script guarantees atomic execution inside Redis, eliminating race conditions while calculating dynamic request window counts.
snippet.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import timefrom django.core.cache import cachefrom django.http import JsonResponseSLIDING_WINDOW_LUA = """local key = KEYS[1]local now = tonumber(ARGV[1])local clearBefore = now - tonumber(ARGV[2])local limit = tonumber(ARGV[3])redis.call('ZREMRANGEBYSCORE', key, 0, clearBefore)local currentRequests = redis.call('ZCARD', key)if currentRequests < limit thenredis.call('ZADD', key, now, now)redis.call('EXPIRE', key, tonumber(ARGV[2]))return 1elsereturn 0end"""class SlidingWindowRateLimitMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):client_ip = request.META.get('REMOTE_ADDR', 'unknown')cache_key = f"ratelimit:{client_ip}"now = time.time()# 100 requests per 60 seconds limitallowed = cache.client.get_client().eval(SLIDING_WINDOW_LUA, 1, cache_key, now, 60, 100)if not allowed:return JsonResponse({"error": "Too many requests"}, status=429)return self.get_response(request)
django
Breakdown
1
local currentRequests = redis.call('ZCARD', key)
Uses Redis sorted sets to count requests strictly within the active sliding time window.
2
redis.call('ZREMRANGEBYSCORE', key, 0, clearBefore)
Removes outdated request timestamps older than the configured sliding window length prior to evaluation.
3
allowed = cache.client.get_client().eval(...)
Executes the Lua script atomically on the Redis client to evaluate limit compliance without thread lock contention.