____ __ _
/ __/___ ______/ /_____ _____ (_)
/ /_/ __ `/ ___/ __/ __ `/ __ \/ /
/ __/ /_/ (__ ) /_/ /_/ / /_/ / /
/_/ \__,_/____/\__/\__,_/ .___/_/
/_/
___ ___ _ __
_____/ (_)___/ (_)___ ____ _ _ __(_)___ ____/ /___ _ __
/ ___/ / / __ / / __ \/ __ `/ | | /| / / / __ \/ __ / __ \ | /| / /
(__ ) / / /_/ / / / / / /_/ / | |/ |/ / / / / / /_/ / /_/ / |/ |/ /
/____/_/_/\__,_/_/_/ /_/\__, / |__/|__/_/_/ /_/\__,_/\____/|__/|__/
/____/
📦 installation
pip install fastapi-sliding-window
📑 quick start
from fastapi import FastAPI, Depends
from fastapi_sliding_window import RateLimit
app = FastAPI()
@app.get("/login", dependencies=[Depends(RateLimit(requests=5, window_seconds=60))])
async def login():
return {"status": "ok"}
🧩 features
- 🎯 3 algorithms — Sliding Window Log (exact), Sliding Window Counter (O(1) memory), Fixed Window
- 💾 in-memory — no Redis required, zero external dependencies
- 🔧 two usage styles —
Depends(RateLimit(...))per-route orRateLimitMiddlewareglobally - 📝 standard headers —
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset,Retry-After - ✅ fully typed —
py.typedmarker included - 🚀 async-native — built on
asyncio.Lockfor thread safety
📖 usage
Depends (per-route)
from fastapi import Depends
from fastapi_sliding_window import RateLimit, Algorithm
# Sliding Window Log (default, most accurate)
@app.get("/api/data", dependencies=[
Depends(RateLimit(requests=100, window_seconds=60))
])
async def get_data():
return {"data": "..."}
# Fixed Window (fastest, O(1) memory)
@app.post("/api/upload", dependencies=[
Depends(RateLimit(requests=10, window_seconds=60, algorithm=Algorithm.FIXED_WINDOW))
])
async def upload():
return {"status": "uploaded"}
# custom key function (per-user instead of per-IP)
async def user_key(request):
return request.headers.get("X-User-ID", "anonymous")
@app.get("/api/profile", dependencies=[
Depends(RateLimit(requests=50, window_seconds=60, key_func=user_key))
])
async def profile():
return {"user": "..."}
Middleware (global)
from fastapi_sliding_window import RateLimitMiddleware, Algorithm
app.add_middleware(
RateLimitMiddleware,
requests=100,
window_seconds=60.0,
algorithm=Algorithm.SLIDING_WINDOW_LOG,
exclude_paths=["/health"], # skip rate limiting for these paths
)
📊 algorithms
| Algorithm | Accuracy | Memory | Speed | Best for |
|---|---|---|---|---|
| Sliding Window Log | 100% | O(requests/window) | O(1) amortized | accuracy-critical endpoints |
| Sliding Window Counter | ~99% | O(1) per key | O(1) | high-traffic APIs |
| Fixed Window | ~50% (boundary burst) | O(1) per key | O(1) | simple quotas |
Sliding Window Log
Stores a timestamp for every request. Prunes entries outside the window on each check. Perfectly accurate, memory grows linearly with request volume within the window.
Sliding Window Counter
Maintains two counters (current and previous window) and computes a weighted average. Near-accurate with constant memory. Best balance of accuracy and performance.
Fixed Window
Simple counter per time bucket. Suffers from boundary burst (clients can send 2x the limit across a window boundary).
📝 HTTP headers
successful responses include:
| Header | Description |
|---|---|
X-RateLimit-Limit |
maximum requests allowed |
X-RateLimit-Remaining |
requests remaining in window |
X-RateLimit-Reset |
unix timestamp when window resets |
Retry-After |
seconds until next request is allowed (429, middleware only) |
🔗 API Reference
RateLimit(requests, window_seconds, algorithm, key_func, include_headers)
FastAPI dependency for per-route rate limiting.
| Parameter | Type | Default | Description |
|---|---|---|---|
requests |
int |
required | max requests per window |
window_seconds |
float |
required | window duration in seconds |
algorithm |
Algorithm |
SLIDING_WINDOW_LOG |
rate limiting algorithm |
key_func |
KeyFunc |
IP-based | function to extract client key |
include_headers |
bool |
True |
add rate limit headers |
RateLimitMiddleware(requests, window_seconds, algorithm, key_func, include_headers, exclude_paths)
Starlette middleware for global rate limiting.
| Parameter | Type | Default | Description |
|---|---|---|---|
requests |
int |
100 |
max requests per window |
window_seconds |
float |
60.0 |
window duration in seconds |
algorithm |
Algorithm |
SLIDING_WINDOW_LOG |
rate limiting algorithm |
key_func |
KeyFunc |
IP-based | function to extract client key |
include_headers |
bool |
True |
add rate limit headers |
exclude_paths |
list[str] |
None |
paths to skip rate limiting |
📜 license
Metadata
Release files for fastapi-sliding-window 0.2.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 | |
|---|---|---|---|
| fastapi_sliding_window-0.2.0.tar.gz | 14.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_sliding_window-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.9 kB
Release files / fastapi_sliding_window-0.2.0.tar.gz
| Download URL | fastapi_sliding_window-0.2.0.tar.gz |
|---|---|
| Size | 14.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d566ab7426d4ae074b639fc6899eae8af19c93e376db780828cb20caac6d2749
|
|
BLAKE2b-256 checksum How to use checksums |
9394d60a9aadaa6c22769350dd02a7d452e95934ed2a0116d0b124d78970b933
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Release files / fastapi_sliding_window-0.2.0-py3-none-any.whl
| Download URL | fastapi_sliding_window-0.2.0-py3-none-any.whl |
|---|---|
| Size | 12.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
79f656a992bf600106ec48752661883dc96f293a6bf6bfde73fbf5cc9af9a205
|
|
BLAKE2b-256 checksum How to use checksums |
02304455f9ea7f70a776de71f5f2b313597d6b2071c7f148eafd38111b828572
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|