FastAPI — Modern Async Web Framework
High-performance Python web framework built on Starlette and Pydantic. Automatic OpenAPI docs, type-safe request validation, async-first design, and dependency injection out of the box.
Installation
uv add fastapi
uv add "uvicorn[standard]" # ASGI server with uvloop & httptools
uv add pydantic-settings # env-based configuration
uv add python-multipart # form/file uploads
uv add python-jose[cryptography] # JWT tokens
uv add passlib[bcrypt] # password hashing
When to Use What
| Feature |
Best for |
Path operations (@app.get) |
Standard REST endpoints |
Depends() |
Shared logic: auth, DB sessions, config |
BackgroundTasks |
Quick fire-and-forget work (emails, logs) |
| WebSocket |
Real-time bidirectional communication |
APIRouter |
Splitting routes into modules |
| Lifespan events |
App-level startup/shutdown (DB pools, caches) |
Section Map
| File |
Topics |
| 01 App & Routing |
App config, path/query params, request/response models, status codes |
| 02 Dependencies & Middleware |
Depends, yield deps, middleware, lifespan, CORS |
| 03 Database Integration |
Async SQLAlchemy, session management, CRUD patterns, repositories |
| 04 Auth & Security |
OAuth2, JWT, password hashing, role-based access, API keys |
| 05 Testing |
TestClient, async tests, dependency overrides, fixtures, coverage |
| 06 Production Patterns |
Project structure, background tasks, WebSocket, error handling, deploy |
| 07 ASGI, Uvicorn, Starlette |
ASGI vs WSGI, Uvicorn role, FastAPI-Starlette stack, when to consider Litestar |
Quick Start
from fastapi import FastAPI
app = FastAPI(title="My API", version="0.1.0")
@app.get("/")
async def root():
return {"message": "Hello, FastAPI"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
uvicorn main:app --reload
| URL |
Purpose |
http://127.0.0.1:8000 |
API root |
http://127.0.0.1:8000/docs |
Swagger UI (interactive) |
http://127.0.0.1:8000/redoc |
ReDoc (read-only docs) |
http://127.0.0.1:8000/openapi.json |
Raw OpenAPI schema |
Response Model Cheat Sheet
| Return type |
What happens |
dict / list |
JSON-serialized as-is |
| Pydantic model |
Validated + serialized via model_dump() |
Response / JSONResponse |
Full control over headers, status, body |
StreamingResponse |
Stream large files or SSE |
FileResponse |
Serve static files |
Quick Rules
- Use async
def — for I/O-bound endpoints; sync def runs in a threadpool.
- Type everything — path params, query params, body models get auto-validated.
- Use
Depends() — never instantiate shared resources inside endpoints.
- Keep routes thin — move business logic to service layer.
- Use
APIRouter — one router per domain/module.
- Use Pydantic models for I/O — separate request and response schemas.
- Lifespan over events — use
lifespan context manager, not deprecated on_event.
See also