Skip to main content

High-performance async rate limiter for FastAPI with Redis or native in-memory backend

Project description

fastapi‑easylimiter

GitHub stars GitHub forks GitHub issues GitHub license PyPI

An ASGI async rate-limiting middleware for FastAPI with Redis or in-memory caching. Designed to handle auto-generated routes (such as those provided by FastAPI-Users) without requiring decorators, purely out of simplicity.

Features

  • Async rate limiting
  • Optional temporary IP bans
    • Configurable threshold (default 10 violations)
    • Sliding 30-min offense window
    • 5-min ban on repeat abuse
  • Cache
    • Redis
    • In-Memory (single worker dev)
  • Path Based Rules
  • Multi-rule prefix matching
    • Capable of global rate-limits and per-route
  • Standard rate-limit headers
    • X-RateLimit-Limit
    • X-RateLimit-Remaining
    • X-RateLimit-Reset
    • Retry-After on 429 responses
    • Tracking for remaining time sent in headers
  • Proxy Aware
    • Uses 'X-Forwarded-For' only when the sender is trusted
    • Rejects spoofed XFF headers
    • Uses 'CF-Connecting-IP' and chekcks connection IP against CF CIDR list
    • Falls back to ASGI scope["client"] if no trusted headers exist
  • Zero Dependencies Beyond Redis Client
    • Starlette-style ASGI middleware

Installation

pip install fastapi-easylimiter

Usage

from fastapi import FastAPI
from fastapi_easylimiter import AsyncRedisBackend, InMemoryBackend, RateLimiterMiddleware
import redis.asyncio as redis_async

app = FastAPI()

REDIS_URL = "redis://localhost:6379/0"

# Redis backend (recommended for multi-instance deployments)
redis_client = redis_async.from_url(REDIS_URL, decode_responses=True)
backend = AsyncRedisBackend(redis_client)

# Or for single-instance/local development:
# backend = InMemoryBackend()

rules = {
    "/": {"limit": 600, "period": 60},          # GLOBAL: 600 req/min per IP
    "/api/": {"limit": 10, "period": 1},
    "/api/users": {"limit": 1, "period": 2},
}

app.add_middleware(
    RateLimiterMiddleware,
    rules=rules,
    backend=backend,
    trusted_proxies=["127.0.0.1"],
    cloudflare=True, # enables CF-Connecting-IP
    enable_bans=True,         # ← new: turn on/off banning
    ban_threshold=15,         # ← violations before ban
    ban_duration=900,         # ← ban length in seconds
    offenses_ttl=1800,        # ← offense counting window
)

Rules are automatically sorted longest-first as seen in the code example.

A request to /api/users/me will match:

  • /api/users
  • /api

If ANY rule is exceeded → request becomes 429.

Uses Atomic LUA script:

local count = redis.call('INCR', key)
if count == 1 then redis.call('EXPIRE', key, period) end

Keys follow the pattern - rl:{client_ip}:{prefix}, which is saved as rl:203.0.113.5:/api

Parameter Type Description
app ASGIApp FastAPI/ASGI app
rules dict { prefix: {"limit": int, "period": int} }
backend Redis or InMemory backend Rate-limit storage
trusted_proxies list[str] Proxies allowed to trust XFF headers
cloudflare bool Enable Cloudflare IP extraction
enable_bans bool Enable temporary IP bans
ban_threshold int Violations before ban
ban_duration int Ban length in seconds
offenses_ttl int Offense counting window in seconds

Contributing

Contributions and forks are always welcome! Feel free to adapt and improve for your own needs.

Support

Buy Me a Coffee

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_easylimiter-0.2.8.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_easylimiter-0.2.8-py3-none-any.whl (8.1 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_easylimiter-0.2.8.tar.gz.

File metadata

  • Download URL: fastapi_easylimiter-0.2.8.tar.gz
  • Upload date:
  • Size: 6.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for fastapi_easylimiter-0.2.8.tar.gz
Algorithm Hash digest
SHA256 4ff2b1216848773d6d5a8d2616efd123c964e75bff357bd0e8ca88c6c8468ad8
MD5 5eb6b16834aca9f81687eb10b2a5d0e5
BLAKE2b-256 758105c386cecd4ad6dd0ea95c36d1e1863c12035cce8c43c757851855efd9ba

See more details on using hashes here.

File details

Details for the file fastapi_easylimiter-0.2.8-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_easylimiter-0.2.8-py3-none-any.whl
Algorithm Hash digest
SHA256 157cf47c9f1f1041da198ab1d147e9d2dcb16fc92ab66f9f8e85917c8901cbb1
MD5 4d45cb6ebd153aceb4e230953f6a898d
BLAKE2b-256 a347cfe8d49c854e39ccaf539969e3d827d7ad582e3bc3c2990b8e3c58ae8a37

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