Skip to main content

Flexible rate limiting for FastAPI using pyrate-limiter

Project description

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

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

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.

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