Sheriff 🤠
An elegant, thread-safe, in-memory rate limiter for Python.
sheriff implements the Token Bucket algorithm, ensuring complete thread-safety with fine-grained locking and zero-leak memory management. It is designed to be lightweight, dependency-free, and extremely easy to integrate into any application or web framework (like FastAPI).
Features
- 🔒 Thread-Safe: Uses fine-grained concurrent locks to ensure rate-limiting consistency across multiple threads.
- 🪣 Token Bucket Algorithm: Standard token bucket rate limiting with lazy, high-precision token replenishment.
- 🧹 Self-Cleaning (Lazy Cleanup): Prunes stale/fully-replenished buckets from memory automatically to prevent memory leaks.
- ⚡ Zero Dependencies: Pure Python, built using standard library tools.
- 🚀 FastAPI / Web Ready: Fits perfectly into FastAPI's dependency injection (
Depends) system.
Installation
Install using pip:
pip install sheriff-limiter
Quick Start
Basic Usage
Use is_allowed for a simple boolean check:
from sheriff import RateLimiter
# Default: 10 requests capacity, replenishes 1 token per second
limiter = RateLimiter()
# Check if allowed
if limiter.is_allowed("user_ip_address"):
print("Request allowed!")
else:
print("Rate limit exceeded.")
Configuration Options
Initialize the limiter with custom parameters:
from sheriff import RateLimiter
# Configured for max 100 requests per minute
limiter = RateLimiter(max_requests=100, period=60.0)
# Or set capacity and refill rate directly
# Capacity of 5 tokens, refilling 0.5 tokens/sec
limiter = RateLimiter(capacity=5.0, refill_rate=0.5)
Advanced Features
1. Raising Exceptions on Exceeding Limits
You can use .check() which raises a RateLimitExceeded exception. The exception contains a retry_after parameter telling you how long to wait in seconds.
from sheriff import RateLimiter, RateLimitExceeded
limiter = RateLimiter(max_requests=5, period=10.0)
try:
# Consume 1 token
limiter.check("client_1")
except RateLimitExceeded as e:
print(f"Rate limit exceeded! Retry after {e.retry_after:.2f} seconds.")
2. Manual Resets
Clear specific keys or reset all rate limits entirely:
# Reset a single client
limiter.reset("client_1")
# Reset all clients and clear the memory cache
limiter.reset_all()
FastAPI Integration
sheriff is perfect for FastAPI dependencies. Here is how you can use it to rate-limit endpoints by IP address:
from fastapi import FastAPI, Depends, Request, HTTPException, status
from sheriff import RateLimiter, RateLimitExceeded
app = FastAPI()
# 100 requests per minute limit
limiter = RateLimiter(max_requests=100, period=60.0)
def rate_limit(request: Request):
client_ip = request.client.host if request.client else "unknown"
try:
limiter.check(client_ip)
except RateLimitExceeded as e:
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Too many requests. Please slow down.",
headers={"Retry-After": str(int(e.retry_after or 0))}
)
@app.get("/items", dependencies=[Depends(rate_limit)])
async def read_items():
return {"status": "ok"}
License
MIT License. See LICENSE for details.
Release files for sheriff-limiter 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sheriff_limiter-0.1.0.tar.gz | 6.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sheriff_limiter-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.9 kB
Release files / sheriff_limiter-0.1.0.tar.gz
| Download URL | sheriff_limiter-0.1.0.tar.gz |
|---|---|
| Size | 6.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f832f6410f75d50c2c92266bc907f8547c8bd3a823da7dbe2c742a9ab6eb7bdb
|
|
BLAKE2b-256 checksum How to use checksums |
dad1531843c690f4fabbef292401cf07038d33d38b981debaae12ae5f376a297
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / sheriff_limiter-0.1.0-py3-none-any.whl
| Download URL | sheriff_limiter-0.1.0-py3-none-any.whl |
|---|---|
| Size | 5.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
04025508f2cc3079a06c251ebc9cd372dcd7a01e66ce21cd718d7c1b2febc13a
|
|
BLAKE2b-256 checksum How to use checksums |
0e928f7c6a91be54e40362e8c742fcc2a4dee5a4e647c182226ae62908296156
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|