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

Download files

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

Source Distribution

fapi_limiter-0.2.0.tar.gz (7.6 kB view details)

Uploaded Source

Built Distribution

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

fapi_limiter-0.2.0-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

Details for the file fapi_limiter-0.2.0.tar.gz.

File metadata

  • Download URL: fapi_limiter-0.2.0.tar.gz
  • Upload date:
  • Size: 7.6 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for fapi_limiter-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c5c439da21acf8464bdbc801cf8ceef92315d532ff4abe5e988bf6b8a9ff915d
MD5 98b143a88125e7c91208fb40c3d7d390
BLAKE2b-256 dc384132442ed3cc2c1e3add3ed8a9f6c9551d0db120ceed91f8e09c55c96a2f

See more details on using hashes here.

File details

Details for the file fapi_limiter-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: fapi_limiter-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 10.4 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for fapi_limiter-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fc94b6e487daf0ad667fa2a1429b17c50dd3231ff80bec7d405076d8d7c685df
MD5 ffa9e53504bc97b2d845dd406580609e
BLAKE2b-256 a2ab46e56a964de46a720d173a3ed5f5fd2b625c951a55020de47d27d4c2cf9d

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 files

Supported by

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