p-redis-limiter
Redis token bucket rate limiter for Python and FastAPI.
Installation
pip install p-redis-limiter
Usage
1. Global Middleware (All Endpoints)
Apply a rate limit across all endpoints:
from fastapi import FastAPI
from redis import Redis
from p_redis_limiter import RateLimitMiddleware, Rate
app = FastAPI()
r = Redis(host="localhost", port=6379, decode_responses=True)
# 40 requests per 60 seconds
app.add_middleware(
RateLimitMiddleware,
redis=r,
rates=Rate(40, 60),
)
@app.get("/")
def index():
return {"ok": True}
2. Specific Endpoint Only
To rate limit a specific route instead of the whole application, use RateLimiter with Depends:
from fastapi import FastAPI, Depends
from redis import Redis
from p_redis_limiter import RateLimiter, Rate
app = FastAPI()
r = Redis(host="localhost", port=6379, decode_responses=True)
# 5 requests per 60 seconds for login only
login_limiter = RateLimiter(r, Rate(5, 60), prefix="rate:login")
@app.get("/")
def home():
return {"message": "unlimited"}
@app.post("/login", dependencies=[Depends(login_limiter.as_dependency())])
def login():
return {"message": "login successful"}
3. Multiple Rate Limits
You can define multiple rules (e.g. 5 req/sec burst limit and 100 req/min). If one rule fails, tokens are not deducted from the others:
rates = [
Rate(5, 1), # 5 requests per 1 second
Rate(100, 60), # 100 requests per 60 seconds
]
# Or string shorthand:
rates = ["5/s", "100/m"]
4. Cache TTL
By default, Redis keys expire automatically after max(window * 2, 60) seconds. You can specify a custom TTL:
# Per rate rule:
Rate(40, 60, ttl=120)
# Disable TTL (persist in Redis forever):
Rate(40, 60, ttl=-1)
# Or globally on middleware / limiter:
RateLimitMiddleware(redis=r, rates=Rate(40, 60), ttl=120)
5. Manual Usage (Specify IP Yourself)
If you prefer to get the IP yourself, simply pass your IP variable directly:
from p_redis_limiter import RateLimiter, Rate
limiter = RateLimiter(r, Rate(5, 60))
@app.post("/login")
def login(request: Request):
user_ip = get_my_ip(request) # your own IP variable
# Simple boolean check:
if not limiter.is_allowed(user_ip):
return JSONResponse({"detail": "Too many requests"}, status_code=429)
return {"ok": True}
Or get full details (remaining, retry_after):
result = limiter.check(user_ip)
if not result.allowed:
print(f"Blocked! Retry after {result.retry_after}s")
Options
| Parameter | Type | Default | Description |
|---|---|---|---|
redis |
Redis |
Required | Redis client instance (redis.Redis or redis.asyncio.Redis) |
rates |
Rate / list / str |
Required | Rate rules, e.g. Rate(40, 60) or ["5/s", "100/m"] |
ttl |
int |
Auto | Custom Redis key TTL in seconds |
prefix |
str |
"rate" |
Prefix for Redis keys |
identifier |
Callable / str |
Client IP | Custom function or header name (auto-detects Cloudflare, Nginx, ALB, direct IP) |
exclude_paths |
list[str] |
None |
List of paths to exclude from rate limiting |
error_detail |
str |
"Too many requests" |
Response detail message on 429 |
Release files for p-redis-limiter 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| p_redis_limiter-0.1.1.tar.gz | 10.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| p_redis_limiter-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.8 kB
Release files / p_redis_limiter-0.1.1.tar.gz
| Download URL | p_redis_limiter-0.1.1.tar.gz |
|---|---|
| Size | 10.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dcd81cb96b058f75f244ae53df471870135a0db851672918d3a062b2991198d3
|
|
BLAKE2b-256 checksum How to use checksums |
2818c4605346794af5579f164d1317a5d5e364ee1b77648d6df8e7f09872bd76
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / p_redis_limiter-0.1.1-py3-none-any.whl
| Download URL | p_redis_limiter-0.1.1-py3-none-any.whl |
|---|---|
| Size | 10.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e773ab411c480489505e1f99ff9a064e0e3abc83968faa59411484dce72696f4
|
|
BLAKE2b-256 checksum How to use checksums |
51376f46c2f46b7273645918a370128162b35a81a6e69cf2323e73bca6b9df57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|