Distributed rate limiting with token bucket algorithm and Redis backend
Project description
netrun-ratelimit
Distributed rate limiting with token bucket algorithm and Redis backend.
Features
- Token Bucket Algorithm: Allows bursts while maintaining average rate limits
- Multiple Backends: In-memory for single instances, Redis for distributed systems
- FastAPI Integration: Middleware and decorators for seamless integration
- Async Support: Full async/await support for high-performance applications
- Type-Safe: Complete type hints with py.typed marker
Installation
# Core package (memory backend only)
pip install netrun-ratelimit
# With Redis support
pip install netrun-ratelimit[redis]
# With FastAPI integration
pip install netrun-ratelimit[fastapi]
# All features
pip install netrun-ratelimit[all]
Quick Start
Basic Usage
from netrun_ratelimit import RateLimiter, MemoryBackend
# Create limiter (100 requests per minute)
limiter = RateLimiter(
backend=MemoryBackend(),
rate=100,
period=60,
)
# Check rate limit
result = limiter.check("user:123")
if result.allowed:
# Process request
pass
else:
# Rate limited
print(f"Retry after {result.retry_after} seconds")
With Redis (Distributed)
from netrun_ratelimit import RateLimiter, RedisBackend
backend = RedisBackend(redis_url="redis://localhost:6379")
limiter = RateLimiter(backend=backend, rate=100, period=60)
# Works across multiple application instances
result = limiter.check("user:123")
FastAPI Middleware
from fastapi import FastAPI
from netrun_ratelimit import RateLimiter, MemoryBackend, RateLimitMiddleware
app = FastAPI()
limiter = RateLimiter(backend=MemoryBackend(), rate=100, period=60)
app.add_middleware(
RateLimitMiddleware,
limiter=limiter,
exclude_paths=["/health", "/metrics"],
)
@app.get("/api/data")
async def get_data():
return {"data": "value"}
Route Decorators
from fastapi import FastAPI, Request
from netrun_ratelimit import rate_limit, limit_by_user, limit_by_api_key
app = FastAPI()
# Basic rate limit
@app.get("/api/public")
@rate_limit(rate=10, period=60)
async def public_endpoint(request: Request):
return {"status": "ok"}
# Per-user rate limit
@app.get("/api/user")
@limit_by_user(rate=100, period=60)
async def user_endpoint(request: Request):
return {"status": "ok"}
# Per-API-key rate limit
@app.get("/api/partner")
@limit_by_api_key(rate=1000, period=3600)
async def partner_endpoint(request: Request):
return {"status": "ok"}
Configuration
Use environment variables or Pydantic settings:
from netrun_ratelimit import RateLimitConfig
config = RateLimitConfig(
rate=100, # Requests per period
period=60, # Period in seconds
burst=150, # Max burst size
redis_url="redis://localhost:6379",
key_prefix="myapp:",
include_headers=True,
)
Environment variables (prefixed with RATELIMIT_):
RATELIMIT_RATE=100
RATELIMIT_PERIOD=60
RATELIMIT_REDIS_URL=redis://localhost:6379
HTTP Headers
Rate limit information is returned in standard headers:
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests per period |
X-RateLimit-Remaining |
Remaining requests in current period |
X-RateLimit-Reset |
Unix timestamp when limit resets |
Retry-After |
Seconds until retry (only when limited) |
Exception Handling
from netrun_ratelimit import RateLimitExceeded
from fastapi import HTTPException
try:
result = limiter.check("user:123")
if not result.allowed:
raise RateLimitExceeded(
limit=result.limit,
retry_after=result.retry_after,
)
except RateLimitExceeded as e:
raise HTTPException(
status_code=429,
detail="Too many requests",
headers=e.headers,
)
Token Bucket Algorithm
The token bucket algorithm provides smooth rate limiting with burst capability:
- Bucket starts full with
bursttokens - Each request consumes 1 token
- Tokens refill at
rate/periodtokens per second - Requests are denied when bucket is empty
Example: 100 req/minute with burst of 150
- Can handle initial burst of 150 requests
- Sustained rate limited to ~1.67 requests/second
- Bucket refills even while processing requests
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run with coverage
pytest --cov=netrun_ratelimit
# Type checking
mypy netrun_ratelimit
# Linting
ruff check netrun_ratelimit
License
MIT License - see LICENSE file for details.
Contributing
Contributions welcome! Please read our contributing guidelines and submit pull requests to the main repository.
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 netrun_ratelimit-2.0.0.tar.gz.
File metadata
- Download URL: netrun_ratelimit-2.0.0.tar.gz
- Upload date:
- Size: 25.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79cc052f55d2caf59569416337a6d137da2a3e6ac0d94d3bab2629487f7f8ff0
|
|
| MD5 |
6692a5ed99e9011a73627b40dff8d6c9
|
|
| BLAKE2b-256 |
17da3a548763890c8d47551d8dde55d20b9e585cd8a395e5c91aa3f3a22534cb
|
File details
Details for the file netrun_ratelimit-2.0.0-py3-none-any.whl.
File metadata
- Download URL: netrun_ratelimit-2.0.0-py3-none-any.whl
- Upload date:
- Size: 30.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12e76424cdb5a17a6c23467961d39cb438a77692a14658232b0a9740a7f4db67
|
|
| MD5 |
1c50db7d20741e57a99455256fba6a4a
|
|
| BLAKE2b-256 |
25df11b5201b45a7ae868280a196894840285996535c55bf8d154f1bc927b9ac
|