Skip to main content

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 Depends and 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 + zrangebyscore in RedisBackend are not atomic — consider a Lua script for high-concurrency scenarios

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_multlimiter-0.1.1.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_multlimiter-0.1.1-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

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

Hashes for fastapi_multlimiter-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d6840cf88f5ffe656b5caa5be7b8dacf55c2d6e1356ccecf4db8f8bd52cc2d2e
MD5 859699bd8496f2a2841b274861a3baf9
BLAKE2b-256 927e66f0e5f6650719031c8f01f65aa96b97825857de233314a31efeafccd36a

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_multlimiter-0.1.1.tar.gz:

Publisher: publish.yml on gr1zer1/fastapi-multlimiter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastapi_multlimiter-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_multlimiter-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 56ca916faa7dcf43f171e59279b873b15adb05aa54e798fc7fd0682da6f62893
MD5 758dc923ac7d71dcc8dec135c7bf2e92
BLAKE2b-256 080ef828180932e95dad1c6cafa56767ab535cfec991c1f6201a9bd39667bc8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_multlimiter-0.1.1-py3-none-any.whl:

Publisher: publish.yml on gr1zer1/fastapi-multlimiter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page