Redis-backed sliding-window rate limiter for Python
Project description
sliding-rate-limiter-redis
A Redis-backed sliding window rate limiter for Python.
Why sliding window?
Most rate limiters use a fixed window (e.g. "100 requests per minute, resetting on the clock"). This creates a burst problem: a client can make 100 requests at 00:59 and another 100 at 01:00 — 200 requests in two seconds.
The sliding window log algorithm solves this by tracking the exact timestamp of every request in a Redis sorted set. Only requests within the last window seconds are counted, so the limit is enforced continuously rather than in discrete buckets.
All Redis operations execute atomically via a Lua script, so check-and-increment is race-condition free under high concurrency.
Installation
pip install sliding-rate-limiter-redis
Requires redis-py >= 4.0.0 and a running Redis instance.
Quick start
import redis
from rate_limiter import SlidingWindowLimiter, RateLimitError
r = redis.Redis()
limiter = SlidingWindowLimiter(r, limit=100, window=60, key_prefix="rl")
# Non-throwing: inspect the result yourself
result = limiter.check("user:42")
print(result)
# RateLimitResult(allowed=True, remaining=99, retry_after=None, reset_at=..., limit=100)
# Throwing: raises RateLimitError if the limit is exceeded
try:
limiter.consume("user:42")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
FastAPI middleware example
from fastapi import Request
from fastapi.responses import JSONResponse
@app.middleware("http")
async def rate_limit(request: Request, call_next):
try:
result = limiter.consume(request.client.host)
response = await call_next(request)
response.headers["X-RateLimit-Remaining"] = str(result.remaining)
return response
except RateLimitError as e:
return JSONResponse(
status_code=429,
content={"error": "Too Many Requests"},
headers={"Retry-After": str(e.retry_after)},
)
API
SlidingWindowLimiter(redis, *, limit, window, key_prefix="rl")
| Parameter | Type | Description |
|---|---|---|
redis |
redis.Redis |
Connected redis-py client |
limit |
int |
Maximum requests per window |
window |
int |
Window duration in seconds |
key_prefix |
str |
Redis key prefix. Default: "rl" |
check(identifier) → RateLimitResult
Records the request and returns a result. Does not raise on limit exceeded.
consume(identifier) → RateLimitResult
Same as check() but raises RateLimitError if the limit is exceeded.
RateLimitResult
| Field | Type | Description |
|---|---|---|
allowed |
bool |
Whether the request was allowed |
remaining |
int |
Requests remaining in the current window |
retry_after |
int | None |
Seconds until next request allowed; None if allowed |
reset_at |
datetime |
UTC datetime when the window resets |
limit |
int |
The configured limit |
RateLimitError
Raised by consume() when the limit is exceeded. Carries retry_after, reset_at, and limit.
Full documentation
See the GitHub repository for architecture details, Node.js package, benchmarks, and more.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sliding_rate_limiter_redis-1.0.1.tar.gz.
File metadata
- Download URL: sliding_rate_limiter_redis-1.0.1.tar.gz
- Upload date:
- Size: 4.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30eb4f7ced84e589f08ee2252a6a7e68b07a992361e5ab93f33bc5dd45394107
|
|
| MD5 |
86fbdbedc2e5945e7dee8e85c49ff10e
|
|
| BLAKE2b-256 |
2fd17e1ea60156ae650276ca06f4f1fa124e8a4b5555e370aebe73e8d04ab86d
|
Provenance
The following attestation bundles were made for sliding_rate_limiter_redis-1.0.1.tar.gz:
Publisher:
publish-python.yml on aproothi/sliding-rate-limiter-redis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sliding_rate_limiter_redis-1.0.1.tar.gz -
Subject digest:
30eb4f7ced84e589f08ee2252a6a7e68b07a992361e5ab93f33bc5dd45394107 - Sigstore transparency entry: 1446188853
- Sigstore integration time:
-
Permalink:
aproothi/sliding-rate-limiter-redis@d0834814916b5ad66274aa05638957928f30b16a -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/aproothi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@d0834814916b5ad66274aa05638957928f30b16a -
Trigger Event:
push
-
Statement type:
File details
Details for the file sliding_rate_limiter_redis-1.0.1-py3-none-any.whl.
File metadata
- Download URL: sliding_rate_limiter_redis-1.0.1-py3-none-any.whl
- Upload date:
- Size: 4.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54b5dfc6ac1e9876540aaeaca745e2ba0e6eb724487ff9c86bf7c755a16d1950
|
|
| MD5 |
8bee6c6d2dd58b184cf56acfd0cd285f
|
|
| BLAKE2b-256 |
f6fa3c3a1bf11d7b34551fb91469512c5b33933ad65e7459f4419f71bab816a4
|
Provenance
The following attestation bundles were made for sliding_rate_limiter_redis-1.0.1-py3-none-any.whl:
Publisher:
publish-python.yml on aproothi/sliding-rate-limiter-redis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sliding_rate_limiter_redis-1.0.1-py3-none-any.whl -
Subject digest:
54b5dfc6ac1e9876540aaeaca745e2ba0e6eb724487ff9c86bf7c755a16d1950 - Sigstore transparency entry: 1446188914
- Sigstore integration time:
-
Permalink:
aproothi/sliding-rate-limiter-redis@d0834814916b5ad66274aa05638957928f30b16a -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/aproothi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@d0834814916b5ad66274aa05638957928f30b16a -
Trigger Event:
push
-
Statement type: