Skip to main content

fastlimit

Rate limiting for FastAPI with clean route signatures, IP/user-aware buckets, pluggable backends, and automatic rate limit headers.

from fastapi import FastAPI
from fastlimit import FastLimit, rate_limit

app = FastAPI()

limiter = FastLimit(
    redis_url="redis://localhost:6379",  # omit for the in-memory backend
    user_id_func=lambda request: getattr(request.state, "user_id", None),
)
limiter.init_app(app)


@app.post("/upload", dependencies=[rate_limit(ip="10/min", user="50/min")])
async def upload():
    return {"ok": True}

No Request parameter is required in your route handler, and your handler can keep returning normal FastAPI values such as dictionaries, Pydantic models, or responses.

Why fastlimit?

Many FastAPI rate limiters make rate limiting visible in every route signature or only give you one simple bucket per endpoint. fastlimit is built for APIs that need anonymous and authenticated traffic to be treated differently without leaking that plumbing into application code.

With rate_limit(ip="10/min", user="50/min"), anonymous requests are limited by client IP and authenticated requests are limited by the user ID returned from user_id_func.

Features

  • FastAPI dependency API: dependencies=[rate_limit("10/min")]
  • Decorator API: @limit("10/min")
  • No forced Request argument in route functions
  • IP and authenticated-user buckets
  • In-memory backend for development and tests
  • Redis backend for multi-worker production deployments
  • Sliding window, fixed window, and token bucket algorithms
  • Automatic X-RateLimit-* and Retry-After headers
  • Custom header names and custom 429 responses
  • Request cost support for expensive endpoints
  • Dry-run mode for observing limits before enforcement
  • Exempt IPs and trusted proxy support
  • Typed package (py.typed)

Installation

pip install fastlimit

For Redis-backed limits:

pip install "fastlimit[redis]"

With uv:

uv add fastlimit
uv add "fastlimit[redis]"

Quickstart

Create and register one limiter for your FastAPI app:

from fastapi import FastAPI
from fastlimit import FastLimit

app = FastAPI()

limiter = FastLimit(
    # Use Redis in production. Omit redis_url for the in-memory backend.
    redis_url="redis://localhost:6379",

    # Return a stable user ID for authenticated requests, or None for anonymous.
    user_id_func=lambda request: getattr(request.state, "user_id", None),
)
limiter.init_app(app)

Add limits to routes:

from fastapi import APIRouter
from fastlimit import rate_limit

router = APIRouter()


@router.post("/register", dependencies=[rate_limit("10/min")])
async def register():
    return {"ok": True}


@router.post("/upload", dependencies=[rate_limit(ip="5/min", user="50/min")])
async def upload():
    return {"ok": True}

The shorthand rate_limit("10/min") is equivalent to rate_limit(ip="10/min").

Decorator style

If you prefer decorators:

from fastlimit import limit


@router.get("/feed")
@limit("100/min")
async def feed():
    return {"items": []}

The decorator injects a hidden FastAPI dependency, so the route function still does not need a Request parameter.

Rate strings

Rate strings use the format limit/window:

rate_limit("5/s")
rate_limit("10/min")
rate_limit("100/hour")
rate_limit("1000/day")
rate_limit("3/5min")

Supported units include seconds, minutes, hours, and days, with common aliases such as s, sec, min, hour, and day.

Backends

fastlimit ships with two backends:

  • MemoryBackend, used by default, stores counters in the current Python process. It is useful for development, tests, and single-process apps.
  • RedisBackend, enabled with redis_url, shares counters across workers and should be used for multi-process or production deployments.
from fastlimit import FastLimit

limiter = FastLimit()  # in-memory
limiter = FastLimit(redis_url="redis://localhost:6379")  # Redis

Custom backends can be passed with FastLimit(backend=...) by implementing the fastlimit.backends.Backend protocol.

Algorithms

Choose the algorithm when creating the limiter:

from fastlimit import Algorithm, FastLimit

FastLimit(algorithm=Algorithm.SLIDING_WINDOW)  # default
FastLimit(algorithm=Algorithm.FIXED_WINDOW)
FastLimit(algorithm=Algorithm.TOKEN_BUCKET)
  • SLIDING_WINDOW: best default for most APIs; smooth rolling windows.
  • FIXED_WINDOW: simple counters with fixed reset boundaries.
  • TOKEN_BUCKET: allows short bursts while maintaining a long-term rate.

Response headers

Allowed requests include:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1781736212

Blocked requests return HTTP 429 and include:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1781736212
Retry-After: 41

Header names can be customized with HeaderConfig, or disabled entirely.

Advanced options

from fastlimit import FastLimit, HeaderConfig

limiter = FastLimit(
    redis_url="redis://localhost:6379",
    key_prefix="my_api",
    headers=HeaderConfig(
        limit="RateLimit-Limit",
        remaining="RateLimit-Remaining",
        reset="RateLimit-Reset",
    ),
    exempt_ips={"127.0.0.1"},
    trusted_proxies=1,
    dry_run=False,
)

Individual routes can also set a request cost:

@router.post("/export", dependencies=[rate_limit("100/hour", cost=10)])
async def export():
    ...

Documentation

Development

This project uses Python 3.11+ and uv.

uv sync --all-extras --dev
uv run pytest
uv run ruff check src tests
uv run mypy

Build the package:

uv build

Serve the docs locally:

uv run mkdocs serve

License

MIT

Metadata

Release files for fastlimit 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastlimit 0.1.1
File Size Uploaded
fastlimit-0.1.1.tar.gz 15.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fastlimit 0.1.1
File Interpreter ABI Platform
fastlimit-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 36.1 kB

Release files / fastlimit-0.1.1.tar.gz

Download URL fastlimit-0.1.1.tar.gz
Size 15.0 kB
Tags Source
SHA-256 checksum
How to use checksums
55c92defc0d271dba5be5b8892ca7409cb4de43e4670b7dab99f90c026e395ac
BLAKE2b-256 checksum
How to use checksums
f121d45865d12d154c8ce9dd021e0d3b84d42e7ff3a0427b57dc01e24719d584
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 18, 2026.

Transparency log

Release files / fastlimit-0.1.1-py3-none-any.whl

Download URL fastlimit-0.1.1-py3-none-any.whl
Size 21.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fa71b5463413a96c0391b1279402e47b04a0a7536d879b8eb1d915a9309d7311
BLAKE2b-256 checksum
How to use checksums
8d7e12ed7b64ec195816e97ab6142b198e7567cf2378e4ee9dc5182f16062bd7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page