FastAPI
FastAPI: the framework that made Python APIs feel modern. Type hints become validation, validation becomes docs — Swagger UI for free.
▶ Watch this reelWhat you'll learn
- Routes & models
- Dependency injection
- Middleware, background & streaming
- Auth & docs
Remember this
- Type-hinted function signatures ARE the contract: Pydantic validates requests/responses, bad input dies as 422 before your code
- Depends() gives .NET-style DI with per-request caching, teardown via yield, and test overrides — inject db/vector store/LLM clients
- SSE via EventSourceResponse streams LLM tokens to browsers; middleware + BackgroundTasks + /docs OpenAPI complete the production picture
Routes & models
- Decorated functions = controllers; path/query params typed in the signature.
- Pydantic BaseModel: request validation + response shaping; 422s free.
- async def routes run on the event loop — await LLM/vector calls directly.
Dependency injection
Depends(provider): per-request caching, chains compose, teardown viayield.app.dependency_overrides[...]in tests — swap at the seam.- Inject db sessions, vector store, LLM clients uniformly.
Middleware / background / streaming
- Middleware: request-wide concerns (request-id, timing). CORS: explicit origins.
- BackgroundTasks: fire-and-forget AFTER response — never for needed results.
EventSourceResponse(SSE): re-emit httpx LLM streams to browsers.
Auth & docs
- OAuth2PasswordBearer + JWT verify (RS256 for multi-service: public key verifies).
- OpenAPI + Swagger UI at
/docs, generated from type hints. - Run with uvicorn (ASGI). --reload = dev only.
Code: A minimal production-shaped FastAPI skeleton
from fastapi import FastAPI, Depends, HTTPException
from pydantic import BaseModel, Field
from sse_starlette.sse import EventSourceResponse
app = FastAPI(title="RAG Service")
class Ask(BaseModel):
question: str = Field(min_length=3)
stream: bool = True
async def get_store():
async with VectorStore.connect() as vs: # per-request, auto-close
yield vs
@app.post("/ask")
async def ask(
req: Ask,
user: User = Depends(get_current_user),
store: VectorStore = Depends(get_store),
):
async def gen():
async for token in rag.stream(req.question, store):
yield {"data": token}
return EventSourceResponse(gen())
# Run: uvicorn app:app --reload
# Docs: http://localhost:8000/docs ← Swagger UI, already complete