How to Implement Rate Limiting in FastAPI Easily
To implement rate limiting in
FastAPI, use middleware like slowapi which integrates with Starlette to limit requests per client IP. You define limits with decorators or globally to control how many requests a user can make in a time window.Syntax
Rate limiting in FastAPI is commonly done using the slowapi library which provides a decorator and middleware. You wrap your route functions with @limiter.limit("5/minute") to allow 5 requests per minute per client IP. The middleware tracks requests and blocks excess calls.
Key parts:
Limiter: The main rate limiter instance.limiter.limit(): Decorator to set limits on routes.add_middleware: Adds the limiter middleware to FastAPI.
python
from fastapi import FastAPI from slowapi import Limiter from slowapi.util import get_remote_address from slowapi.middleware import SlowAPIMiddleware app = FastAPI() limiter = Limiter(key_func=get_remote_address) app.state.limiter = limiter app.add_middleware(SlowAPIMiddleware) @app.get("/") @limiter.limit("5/minute") async def home(): return {"message": "Hello, world!"}
Example
This example shows a FastAPI app with rate limiting set to 3 requests per minute per IP on the root endpoint. If the limit is exceeded, the client receives a 429 Too Many Requests error.
python
from fastapi import FastAPI, Request from slowapi import Limiter from slowapi.util import get_remote_address from slowapi.middleware import SlowAPIMiddleware from slowapi.errors import RateLimitExceeded from fastapi.responses import JSONResponse app = FastAPI() limiter = Limiter(key_func=get_remote_address) app.state.limiter = limiter app.add_middleware(SlowAPIMiddleware) @app.exception_handler(RateLimitExceeded) async def rate_limit_handler(request: Request, exc: RateLimitExceeded): return JSONResponse( status_code=429, content={"detail": "Rate limit exceeded. Try again later."} ) @app.get("/") @limiter.limit("3/minute") async def read_root(): return {"message": "Welcome! You have access."}
Output
HTTP 200 OK with JSON {"message": "Welcome! You have access."} for first 3 requests per minute
HTTP 429 Too Many Requests with JSON {"detail": "Rate limit exceeded. Try again later."} after limit exceeded
Common Pitfalls
- Not adding
SlowAPIMiddlewareto the FastAPI app causes the limiter to not work. - Forgetting to set
app.state.limiterleads to errors. - Using a wrong
key_funccan cause all users to share the same limit. - Not handling
RateLimitExceededexception results in default error responses.
Always test your limits and customize error handling for better user experience.
python
from fastapi import FastAPI from slowapi import Limiter from slowapi.util import get_remote_address from slowapi.middleware import SlowAPIMiddleware app = FastAPI() limiter = Limiter(key_func=get_remote_address) # Missing middleware below causes limiter to not work # app.add_middleware(SlowAPIMiddleware) @app.get("/") @limiter.limit("2/minute") async def home(): return {"message": "Hello"} # Correct way: app.add_middleware(SlowAPIMiddleware) app.state.limiter = limiter
Quick Reference
Rate Limiting Cheat Sheet for FastAPI with slowapi:
| Feature | Usage |
|---|---|
| Install | pip install slowapi |
| Setup Limiter | limiter = Limiter(key_func=get_remote_address) |
| Add Middleware | app.add_middleware(SlowAPIMiddleware) |
| Set Limit on Route | @limiter.limit("5/minute") |
| Handle Limit Exceeded | Catch RateLimitExceeded exception |
| Feature | Usage |
|---|---|
| Install | pip install slowapi |
| Setup Limiter | limiter = Limiter(key_func=get_remote_address) |
| Add Middleware | app.add_middleware(SlowAPIMiddleware) |
| Set Limit on Route | @limiter.limit("5/minute") |
| Handle Limit Exceeded | Catch RateLimitExceeded exception |
Key Takeaways
Use the slowapi library with FastAPI to easily add rate limiting.
Always add SlowAPIMiddleware and set app.state.limiter for proper functionality.
Define limits per route using the @limiter.limit decorator with a time window.
Handle RateLimitExceeded exceptions to customize error responses.
Test your rate limits to ensure they work as expected for your users.