Skip to main content

Async rate limiter for FastAPI with fixed-window, sliding-window and token bucket algorithms

Project description

FastAPI Limiter

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

Project Structure

.
├── 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
├── pytest.ini
├── requirements.txt
└── .github/workflows/ci.yml

Requirements

  • Python 3.11+
  • Redis — required only for Redis-backed routes and Redis tests

Installation

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
GET /redis/tb          Token bucket, 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_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")

Running Tests

docker run --rm -p 6379:6379 redis:7
pytest

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.0.tar.gz (6.7 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.0-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_multlimiter-0.1.0.tar.gz.

File metadata

  • Download URL: fastapi_multlimiter-0.1.0.tar.gz
  • Upload date:
  • Size: 6.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fastapi_multlimiter-0.1.0.tar.gz
Algorithm Hash digest
SHA256 542d8fbc10189244e78fcc24dd10fef90344011ac783c3e775494b5dcf774911
MD5 3e5cfb3cca824b7df22671f98c0b6137
BLAKE2b-256 00182a19673d42bfedd3c89ac5e62f8c913797d3dd8a6a10510a4e49c4b5c21e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fastapi_multlimiter-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fastapi_multlimiter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 22af11f941b9eadda4ca5ba1643e28c52925c7cf82473370dd58eacd9a694397
MD5 ebd72bb637dac94c22879c3a9bd1a7df
BLAKE2b-256 0b25bb8fad8a5dd277f750c2ec26c5836b663015179fff31743f4a25e39f1f60

See more details on using hashes here.

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