Files
fastapi-traffic/docs/getting-started/quickstart.rst
zanewalker f3453cb0fc release: bump version to 0.3.0
- Refactor Redis backend connection handling and pool management
- Update algorithm implementations with improved type annotations
- Enhance config loader validation with stricter Pydantic schemas
- Improve decorator and middleware error handling
- Expand example scripts with better docstrings and usage patterns
- Add new 00_basic_usage.py example for quick start
- Reorganize examples directory structure
- Fix type annotation inconsistencies across core modules
- Update dependencies in pyproject.toml
2026-03-17 21:04:34 +00:00

221 lines
6.2 KiB
ReStructuredText

Quickstart
==========
Let's get rate limiting working in your FastAPI app. This guide covers the basics —
you'll have something running in under five minutes.
Your First Rate Limit
---------------------
The simplest way to add rate limiting is with the ``@rate_limit`` decorator:
.. code-block:: python
from fastapi import FastAPI, Request
from fastapi_traffic import rate_limit
app = FastAPI()
@app.get("/api/hello")
@rate_limit(10, 60) # 10 requests per 60 seconds
async def hello(request: Request):
return {"message": "Hello, World!"}
That's the whole thing. Let's break down what's happening:
1. The decorator takes two arguments: ``limit`` (max requests) and ``window_size`` (in seconds)
2. Each client is identified by their IP address by default
3. When a client exceeds the limit, they get a 429 response with a ``Retry-After`` header
.. note::
The ``request: Request`` parameter is required. FastAPI Traffic needs access to the
request to identify the client and track their usage.
Testing It Out
--------------
Fire up your app and hit the endpoint a few times:
.. code-block:: bash
# Start your app
uvicorn main:app --reload
# In another terminal, make some requests
curl -i http://localhost:8000/api/hello
You'll see headers like these in the response:
.. code-block:: http
HTTP/1.1 200 OK
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 9
X-RateLimit-Reset: 1709834400
After 10 requests, you'll get:
.. code-block:: http
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
Choosing an Algorithm
---------------------
Different situations call for different rate limiting strategies. Here's a quick guide:
.. code-block:: python
from fastapi_traffic import rate_limit, Algorithm
# Token Bucket - great for APIs that need burst handling
# Allows short bursts of traffic, then smooths out
@app.get("/api/burst-friendly")
@rate_limit(100, 60, algorithm=Algorithm.TOKEN_BUCKET, burst_size=20)
async def burst_endpoint(request: Request):
return {"status": "ok"}
# Sliding Window - most accurate, but uses more memory
# Perfect when you need precise rate limiting
@app.get("/api/precise")
@rate_limit(100, 60, algorithm=Algorithm.SLIDING_WINDOW)
async def precise_endpoint(request: Request):
return {"status": "ok"}
# Fixed Window - simple and efficient
# Good for most use cases, slight edge case at window boundaries
@app.get("/api/simple")
@rate_limit(100, 60, algorithm=Algorithm.FIXED_WINDOW)
async def simple_endpoint(request: Request):
return {"status": "ok"}
See :doc:`/user-guide/algorithms` for a deep dive into each algorithm.
Rate Limiting by API Key
------------------------
IP-based limiting is fine for public endpoints, but for authenticated APIs you
probably want to limit by API key:
.. code-block:: python
def get_api_key(request: Request) -> str:
"""Extract API key from header, fall back to IP."""
api_key = request.headers.get("X-API-Key")
if api_key:
return f"key:{api_key}"
# Fall back to IP for unauthenticated requests
return request.client.host if request.client else "unknown"
@app.get("/api/data")
@rate_limit(1000, 3600, key_extractor=get_api_key) # 1000/hour per API key
async def get_data(request: Request):
return {"data": "sensitive stuff"}
Global Rate Limiting with Middleware
------------------------------------
Sometimes you want a blanket rate limit across your entire API. That's what
middleware is for:
.. code-block:: python
from fastapi_traffic.middleware import RateLimitMiddleware
app = FastAPI()
app.add_middleware(
RateLimitMiddleware,
limit=1000,
window_size=60,
exempt_paths={"/health", "/docs", "/openapi.json"},
)
# All endpoints now have a shared 1000 req/min limit
@app.get("/api/users")
async def get_users():
return {"users": []}
@app.get("/api/posts")
async def get_posts():
return {"posts": []}
Using a Persistent Backend
--------------------------
The default memory backend works great for development, but it doesn't survive
restarts and doesn't work across multiple processes. For production, use SQLite
or Redis:
**SQLite** — Good for single-node deployments:
.. code-block:: python
from fastapi_traffic import RateLimiter, SQLiteBackend
from fastapi_traffic.core.limiter import set_limiter
# Set up persistent storage
backend = SQLiteBackend("rate_limits.db")
limiter = RateLimiter(backend)
set_limiter(limiter)
@app.on_event("startup")
async def startup():
await limiter.initialize()
@app.on_event("shutdown")
async def shutdown():
await limiter.close()
**Redis** — Required for distributed systems:
.. code-block:: python
from fastapi_traffic import RateLimiter
from fastapi_traffic.backends.redis import RedisBackend
from fastapi_traffic.core.limiter import set_limiter
@app.on_event("startup")
async def startup():
backend = await RedisBackend.from_url("redis://localhost:6379/0")
limiter = RateLimiter(backend)
set_limiter(limiter)
await limiter.initialize()
Handling Rate Limit Errors
--------------------------
By default, exceeding the rate limit raises a ``RateLimitExceeded`` exception that
returns a 429 response. You can customize this:
.. code-block:: python
from fastapi import Request
from fastapi.responses import JSONResponse
from fastapi_traffic import RateLimitExceeded
@app.exception_handler(RateLimitExceeded)
async def rate_limit_handler(request: Request, exc: RateLimitExceeded):
return JSONResponse(
status_code=429,
content={
"error": "slow_down",
"message": "You're making too many requests. Take a breather.",
"retry_after": exc.retry_after,
},
)
What's Next?
------------
You've got the basics down. Here's where to go from here:
- :doc:`/user-guide/algorithms` — Understand when to use each algorithm
- :doc:`/user-guide/backends` — Learn about storage options
- :doc:`/user-guide/key-extractors` — Advanced client identification
- :doc:`/user-guide/configuration` — Load settings from files and environment variables