Skip to main content

fapi-limiter

License: MIT

Flexible rate limiting for FastAPI powered by pyrate-limiter.

This project is being developed with AI assistance (GitHub Copilot), but all code, design decisions, and implementation details are reviewed and validated by the author.

Installation

# pip
pip install fapi-limiter

# uv
uv add fapi-limiter

Usage

Middleware (app-wide)

Apply rate limiting to every request in the application.

from fastapi import FastAPI
from pyrate_limiter import Duration, Limiter, Rate

from fapi_limiter import DynamicBucketFactory, RateLimiterMiddleware, setup_inmemory_bucket

app = FastAPI()

limiter = Limiter(DynamicBucketFactory(setup_inmemory_bucket([Rate(10, Duration.MINUTE)])))
app.add_middleware(RateLimiterMiddleware, limiter=limiter)

Dependency (per-route)

Apply rate limiting to specific routes using FastAPI's dependency injection.

from fastapi import Depends, FastAPI
from pyrate_limiter import Duration, Limiter, Rate

from fapi_limiter import DynamicBucketFactory, RateLimiter, setup_inmemory_bucket

app = FastAPI()

limiter = Limiter(DynamicBucketFactory(setup_inmemory_bucket([Rate(10, Duration.MINUTE)])))


@app.get("/limited", dependencies=[Depends(RateLimiter(limiter))])
def limited():
    return {"ok": True}

SQLite backend (persistent, multi-process)

from fastapi import FastAPI
from pyrate_limiter import Duration, Limiter, Rate

from fapi_limiter import DynamicBucketFactory, RateLimiterMiddleware, setup_sqlite_bucket

app = FastAPI()

limiter = Limiter(
    DynamicBucketFactory(
        setup_sqlite_bucket(
            [Rate(10, Duration.MINUTE)],
            db_path="rate_limiter.db",
            use_file_lock=True,  # required when sharing across processes
        )
    )
)
app.add_middleware(RateLimiterMiddleware, limiter=limiter)

Redis backend

from fastapi import FastAPI
from pyrate_limiter import Duration, Limiter, Rate
from redis import Redis

from fapi_limiter import DynamicBucketFactory, RateLimiterMiddleware, setup_redis_bucket

app = FastAPI()

limiter = Limiter(
    DynamicBucketFactory(
        setup_redis_bucket([Rate(10, Duration.MINUTE)], redis=Redis(host="localhost"))
    )
)
app.add_middleware(RateLimiterMiddleware, limiter=limiter)

Response Headers

On every request, the following headers are set:

Header Description
X-RateLimit-Limit Maximum requests allowed in the window
X-RateLimit-Remaining Requests remaining in the current window
X-RateLimit-Reset Unix timestamp (ms) when the window resets

When the limit is exceeded, 429 Too Many Requests is returned and two additional headers are set:

Header Description
Retry-After Unix timestamp (ms) after which the client may retry

Configuration

Both RateLimiterMiddleware and RateLimiter accept the same options:

Parameter Type Default Description
limiter Limiter required A pyrate-limiter Limiter instance
callback CallbackFunction default_callback Called when the limit is exceeded
identifier Callable[[Request], str] get_default_identifier Extracts a key from the request (e.g. IP + path)
blocking bool False Whether to block and wait instead of rejecting

RateLimiterMiddleware also accepts:

Parameter Type Default Description
skip SkipFunction | None None If it returns True, the request bypasses rate limiting

Custom Callback

The callback is invoked when a request is rate-limited. It receives the Request and a headers dict, and should raise an HTTPException:

from fastapi import HTTPException, Request
from fapi_limiter import RateLimiterMiddleware

def my_callback(request: Request, headers=None):
    raise HTTPException(status_code=429, detail="Slow down!", headers=headers)

app.add_middleware(RateLimiterMiddleware, limiter=limiter, callback=my_callback)

Custom Identifier

By default the identifier is {request_method}:{client_ip}:{path}. You can override it to key by user, API token, etc.:

def by_user(request: Request) -> str:
    return request.headers.get("X-User-Id", "anonymous") + ":" + request.url.path

app.add_middleware(RateLimiterMiddleware, limiter=limiter, identifier=by_user)

Skip Function

Use skip on RateLimiterMiddleware to bypass rate limiting for certain requests (e.g. health checks):

def skip_health(request: Request) -> bool:
    return request.url.path == "/health"

app.add_middleware(RateLimiterMiddleware, limiter=limiter, skip=skip_health)

Credits

License

MIT

Metadata

Release files for fapi-limiter 0.2.0

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

Source distribution (sdist)

Source distribution for fapi-limiter 0.2.0
File Size Uploaded
fapi_limiter-0.2.0.tar.gz 7.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fapi-limiter 0.2.0
File Interpreter ABI Platform
fapi_limiter-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 17.9 kB

Release files / fapi_limiter-0.2.0.tar.gz

Download URL fapi_limiter-0.2.0.tar.gz
Size 7.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c5c439da21acf8464bdbc801cf8ceef92315d532ff4abe5e988bf6b8a9ff915d
BLAKE2b-256 checksum
How to use checksums
dc384132442ed3cc2c1e3add3ed8a9f6c9551d0db120ceed91f8e09c55c96a2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / fapi_limiter-0.2.0-py3-none-any.whl

Download URL fapi_limiter-0.2.0-py3-none-any.whl
Size 10.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fc94b6e487daf0ad667fa2a1429b17c50dd3231ff80bec7d405076d8d7c685df
BLAKE2b-256 checksum
How to use checksums
a2ab46e56a964de46a720d173a3ed5f5fd2b625c951a55020de47d27d4c2cf9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.2.0 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