FastAPI Rate Limiting — API Throttling with SlowAPI Middleware
In this tutorial, you will learn about FastAPI Rate Limiting. We cover key concepts, practical examples, and best practices to help you master this topic.
SlowAPI is an async-compatible rate limiting library for FastAPI and Starlette that provides decorator-based and middleware-based rate limiting with support for multiple backends including Redis.
What You'll Learn
- How to install and configure SlowAPI with FastAPI
- How to apply rate limits per-endpoint and globally
- How to use Redis for distributed rate limiting
Why It Matters
FastAPI is the leading Python async web framework. SlowAPI integrates natively with FastAPI's dependency injection system, providing type-safe rate limiting that works seamlessly with async handlers and Websocket endpoints.
Real-World Use
DodaTech's FastAPI microservice uses SlowAPI with three rate limit configurations: global middleware (100 req/min), auth endpoints (5 req/min via dependency), and data endpoints (30 req/min per user). Redis backend ensures consistent limits across multiple uvicorn workers.
flowchart LR
A["Request"] --> B["SlowAPI\nMiddleware"]
B --> C{"Global limit\n100/min"}
C -->|"OK"| D{"Auth endpoint\n5/min"}
D -->|"OK"| E["Route Handler"]
C -->|"Exceeded"| F["429 Response"]
D -->|"Exceeded"| F
style B fill:#dbeafe,stroke:#2563eb
style D fill:#fef3c7,stroke:#d97706
style F fill:#fecaca,stroke:#dc2626
Global Middleware Configuration
from fastapi import FastAPI, Request
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware
limiter = Limiter(key_func=get_remote_address)
app = FastAPI()
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
app.add_middleware(SlowAPIMiddleware)
@app.get("/api/data")
@limiter.limit("100/minute")
async def get_data(request: Request):
return {"data": "response data"}
Per-Endpoint Limits
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
@app.post("/api/auth/login")
@limiter.limit("5/minute")
async def login(request: Request, username: str = Form(...), password: str = Form(...)):
return {"status": "authenticated"}
@app.get("/api/public/search")
@limiter.limit("30/minute")
async def search(request: Request, q: str = Query(...)):
return {"results": search_database(q)}
@app.get("/api/admin/users")
@limiter.limit("100/minute")
async def admin_users(request: Request):
return {"users": get_all_users()}
User-Based Rate Limiting
from slowapi import Limiter
from fastapi import Depends, HTTPException, status
def get_user_key(request: Request):
"""Extract user identifier for rate limiting"""
api_key = request.headers.get("X-API-Key")
if api_key:
return f"apikey:{api_key}"
return get_remote_address(request)
limiter = Limiter(key_func=get_user_key)
@app.get("/api/v2/data")
@limiter.limit("1000/minute")
async def v2_data(request: Request, api_key: str = Depends(validate_api_key)):
return {"data": "v2 response"}
Redis Backend
from slowapi import Limiter
from slowapi.middleware import SlowAPIMiddleware
import aioredis
# Install: pip install slowapi[redis]
limiter = Limiter(
key_func=get_remote_address,
storage_uri="redis://redis-cluster.dodatech.com:6379/0"
)
app = FastAPI()
app.state.limiter = limiter
app.add_middleware(SlowAPIMiddleware)
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
# Custom error response
@app.exception_handler(RateLimitExceeded)
async def custom_rate_limit_handler(request: Request, exc: RateLimitExceeded):
return JSONResponse(
status_code=429,
content={
"error": "rate_limit_exceeded",
"message": str(exc),
"retry_after": 60
},
headers={
"X-RateLimit-Retry-After": "60"
}
)
Common Mistakes
1. Not Adding the Middleware
The @limiter.limit() decorator requires the SlowAPIMiddleware to be added. Without it, the decorator has no effect.
2. Forgetting the request Parameter
The decorated endpoints must accept a request: Request parameter, even if not used. SlowAPI uses it for key extraction.
3. Using get_remote_address Behind a Proxy
Behind a reverse proxy, get_remote_address returns the proxy IP. Use a custom key function that reads the X-Forwarded-For header.
4. Not Customizing Error Responses
The default error response is minimal. Customize the RateLimitExceeded exception handler for user-friendly messages.
5. Applying Limits to WebSocket Endpoints
WebSocket rate limiting requires careful handling. SlowAPI supports it, but the connection lifecycle is different from HTTP.
Practice Questions
- What library provides FastAPI rate limiting?
- How do you apply a rate limit to a specific endpoint?
- What is the key_func parameter used for?
- How do you set up Redis as the rate limit backend?
- Why must the request parameter be present in decorated endpoints?
Answers
- SlowAPI. 2. Use the
@limiter.limit("N/period")decorator. 3. To determine the identifier for rate limiting (IP, user, API key). 4. Setstorage_uri="redis://host:port/db"when creating the Limiter. 5. SlowAPI extracts the rate limit key from the request object.
Challenge
Build a FastAPI application with SlowAPI rate limiting that: uses Redis backend for distributed limiting, has four rate limit levels (public 30/min, auth 5/min, standard 100/min, premium 1000/min), uses custom key functions for user-based and API-key-based limiting, and returns custom 429 JSON responses with upgrade suggestions.
FAQ
Mini Project
Create a FastAPI application with: a global SlowAPI middleware (50 req/min per IP), per-endpoint decorators for auth (5/min), search (30/min), and admin (100/min) endpoints, Redis backend for multi-worker consistency, custom key functions for API key extraction, and a comprehensive test suite with httpx AsyncClient.
What's Next
- Build the complete rate limiting project combining all concepts
- Explore rate limit headers and client-side handling
- Continue to rate limit monitoring with Prometheus and Grafana
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro