Async rate limiter for FastAPI with fixed-window, sliding-window and token bucket algorithms
Project description
fastapi-multlimiter
Async rate limiter for FastAPI with pluggable backends and algorithms.
Features
- Three rate limiting algorithms: fixed-window, sliding-window, token bucket
- Two backends: in-memory (for development and tests) and Redis (for production)
- Two usage styles: FastAPI
Dependsand decorator - Custom key functions (by IP, user, path, or any combination)
- Rate limit response headers:
X-RateLimit-Limit,X-RateLimit-Remaining,Retry-After - GitHub Actions CI with Redis service
Requirements
- Python 3.12+
- Redis server — required only for Redis-backed routes and Redis tests
Installation
Install the package from PyPI:
pip install fastapi-multlimiter
For local development from this repository:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Running Redis
docker run --rm -p 6379:6379 redis:7
Running the App
uvicorn main:app --reload
Demo Endpoints
GET / No limiter
GET /fw Fixed-window, MemoryBackend
GET /sw Sliding-window, MemoryBackend
GET /wrapper/fw Fixed-window as decorator
GET /wrapper/sw Sliding-window as decorator
GET /redis/fw Fixed-window, RedisBackend
GET /redis/sw Sliding-window, RedisBackend
Limit is 5 requests per window. Exceeding it returns HTTP 429 Too Many Requests with headers:
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
Retry-After: 42.0
Usage
Dependency style
from fastapi import Depends, FastAPI
from fastapi_multlimiter.algorithm import FixedWindowAlgorithm
from fastapi_multlimiter.backend import MemoryBackend
app = FastAPI()
limiter = FixedWindowAlgorithm(
backend=MemoryBackend(),
limit=5,
window=60,
)
@app.get("/limited", dependencies=[Depends(limiter.limiter)])
async def limited():
return {"message": "ok"}
Decorator style
from fastapi import FastAPI, Request
from fastapi_multlimiter.algorithm import SlidingWindowAlgorithm
from fastapi_multlimiter.backend import MemoryBackend
app = FastAPI()
limiter = SlidingWindowAlgorithm(
backend=MemoryBackend(),
limit=5,
window=60,
)
@app.get("/limited")
@limiter.limiter_wrapper
async def limited(request: Request):
return {"message": "ok"}
Token bucket
from fastapi import Depends
from fastapi_multlimiter.algorithm import TokenBucketAlgorithm
from fastapi_multlimiter.backend import RedisBackend
limiter = TokenBucketAlgorithm(
backend=RedisBackend("redis://localhost:6379"),
capacity=10,
refill_rate=2.0, # tokens per second
)
@app.get("/limited", dependencies=[Depends(limiter.limiter)])
async def limited():
return {"message": "ok"}
Custom key function
from fastapi import Request
def get_user_key(request: Request) -> str:
return request.headers.get("X-User-ID") or request.client.host
limiter = FixedWindowAlgorithm(
backend=MemoryBackend(),
limit=5,
window=60,
key_func=get_user_key,
)
Redis backend
from fastapi_multlimiter.backend import RedisBackend
backend = RedisBackend("redis://localhost:6379")
Project Structure
.
├── fastapi_multlimiter/
│ ├── algorithm/
│ │ ├── base.py
│ │ ├── fixed_window_algorithm.py
│ │ ├── sliding_window_algorithm.py
│ │ └── token_bucket_algorithm.py
│ └── backend/
│ ├── base.py
│ ├── memory_backend.py
│ └── redis_backend.py
├── tests/
│ └── test_main.py
├── main.py
├── pyproject.toml
├── pytest.ini
├── requirements.txt
└── .github/workflows/ci.yml
Running Tests
docker run --rm -p 6379:6379 redis:7
pytest
Publishing
Releases are published to PyPI by GitHub Actions when a version tag is pushed.
The tag must match the package version in pyproject.toml.
git tag v0.1.0
git push origin v0.1.0
The workflow uses PyPI Trusted Publishing. Configure a trusted publisher for
this repository on PyPI with workflow file .github/workflows/publish.yml and
environment pypi.
Known Limitations
- Sliding-window
zadd+zrangebyscoreinRedisBackendare not atomic — consider a Lua script for high-concurrency scenarios
License
MIT. See LICENSE.
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 fastapi_multlimiter-0.1.1.tar.gz.
File metadata
- Download URL: fastapi_multlimiter-0.1.1.tar.gz
- Upload date:
- Size: 8.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6840cf88f5ffe656b5caa5be7b8dacf55c2d6e1356ccecf4db8f8bd52cc2d2e
|
|
| MD5 |
859699bd8496f2a2841b274861a3baf9
|
|
| BLAKE2b-256 |
927e66f0e5f6650719031c8f01f65aa96b97825857de233314a31efeafccd36a
|
Provenance
The following attestation bundles were made for fastapi_multlimiter-0.1.1.tar.gz:
Publisher:
publish.yml on gr1zer1/fastapi-multlimiter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_multlimiter-0.1.1.tar.gz -
Subject digest:
d6840cf88f5ffe656b5caa5be7b8dacf55c2d6e1356ccecf4db8f8bd52cc2d2e - Sigstore transparency entry: 1548794832
- Sigstore integration time:
-
Permalink:
gr1zer1/fastapi-multlimiter@a2c8263e4aac10155ec91f7bf5cbc0539d38953e -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/gr1zer1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a2c8263e4aac10155ec91f7bf5cbc0539d38953e -
Trigger Event:
push
-
Statement type:
File details
Details for the file fastapi_multlimiter-0.1.1-py3-none-any.whl.
File metadata
- Download URL: fastapi_multlimiter-0.1.1-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56ca916faa7dcf43f171e59279b873b15adb05aa54e798fc7fd0682da6f62893
|
|
| MD5 |
758dc923ac7d71dcc8dec135c7bf2e92
|
|
| BLAKE2b-256 |
080ef828180932e95dad1c6cafa56767ab535cfec991c1f6201a9bd39667bc8c
|
Provenance
The following attestation bundles were made for fastapi_multlimiter-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on gr1zer1/fastapi-multlimiter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_multlimiter-0.1.1-py3-none-any.whl -
Subject digest:
56ca916faa7dcf43f171e59279b873b15adb05aa54e798fc7fd0682da6f62893 - Sigstore transparency entry: 1548794934
- Sigstore integration time:
-
Permalink:
gr1zer1/fastapi-multlimiter@a2c8263e4aac10155ec91f7bf5cbc0539d38953e -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/gr1zer1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a2c8263e4aac10155ec91f7bf5cbc0539d38953e -
Trigger Event:
push
-
Statement type: