Skip to main content

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")

6. Redis Failure & Fallback Handling

Configure what happens if Redis becomes unreachable:

  • Default (on_redis_error="raise"): Raises the Redis connection exception (unhandled errors return HTTP 500).
  • Fail-Open (on_redis_error="allow" or "pass"): Bypasses rate limiting and allows requests through so your service stays online.
  • In-Memory Fallback (on_redis_error="local"): Seamlessly applies an in-memory token bucket rate limit until Redis is back up. Once Redis is reachable again, it automatically recovers and switches back to Redis.
# Option A: Allow requests through if Redis goes down (fail-open)
app.add_middleware(
    RateLimitMiddleware,
    redis=r,
    rates="40/m",
    on_redis_error="allow",
)

# Option B: Fallback to in-memory rate limiting using the same rate rules
app.add_middleware(
    RateLimitMiddleware,
    redis=r,
    rates="40/m",
    on_redis_error="local",
)

# Option C: Fallback to in-memory rate limiting with a specific/stricter rate
app.add_middleware(
    RateLimitMiddleware,
    redis=r,
    rates="40/m",
    on_redis_error="local",
    fallback_rate="10/m",
)

# Also works with RateLimiter / Depends:
login_limiter = RateLimiter(
    r,
    "5/m",
    on_redis_error="local",
    fallback_rate="2/m",
)

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
on_redis_error str / Rate "raise" Behavior when Redis fails: "raise", "allow" (or "pass"), or "local"
fallback_rate Rate / str / list None Custom rate limit rule to use when falling back to "local" mode
redis_retry_interval float 1.0 Seconds to wait before re-probing Redis after a failure

Release files for p-redis-limiter 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for p-redis-limiter 0.1.2
File Size Uploaded
p_redis_limiter-0.1.2.tar.gz 15.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for p-redis-limiter 0.1.2
File Interpreter ABI Platform
p_redis_limiter-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 29.4 kB

Release files / p_redis_limiter-0.1.2.tar.gz

Download URL p_redis_limiter-0.1.2.tar.gz
Size 15.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f350413a46065ef310a80fae462581b08f2aa53235e96006151176e7aa4042a3
BLAKE2b-256 checksum
How to use checksums
c11504c829ad2ff5a41ea633128b0a6b905c4d9d15185059dacdfbde8f4d647c
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.2-py3-none-any.whl

Download URL p_redis_limiter-0.1.2-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
29e151e9ba65792dbb47fbc077be894db62588b284308011771b25df29e9d18a
BLAKE2b-256 checksum
How to use checksums
5e4db706e83aafc5e0e9e318b3ceed718d753b24376a55620cc63ed2db98e639
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page