- FastAPI – async def or def, and How to Tell
The most consequential one-word decision in the framework. What FastAPI does with a def route versus an async def one, why a blocking call inside async def stalls every other request, and the threadpool that makes plain def safe. Then the same eight queries run serially and concurrently and MEASURED — where async wins by 86%, where it loses by 289%, and roughly where the line between them sits.
- FastAPI – Background Tasks and Their Limits
BackgroundTasks runs work after the response is sent, which is the entire feature. What that buys, what it emphatically is not — no retry, no persistence, no visibility — and when to reach for a real queue instead. Then the trap that makes it dangerous: a yield dependency closes BEFORE the task runs, so passing an ORM object half-works, and the half that fails is the half you add later.
- FastAPI – File Uploads Without the Holes
UploadFile, streamed in chunks rather than read into memory, with a size limit enforced during the write because there is no trustworthy length beforehand. Then the three guards an upload endpoint needs: content sniffed from the bytes rather than trusted from a header the client typed, a generated filename because "../../app/main.py" is a valid one, and no partial file left behind on failure.
- FastAPI – Authentication and Authorization
Hashing passwords with bcrypt, issuing a JWT, and verifying it on every request. Then the half everyone skips: authorization as dependencies, so a route signature declares who may call it and the OpenAPI schema documents it for free. Includes why the user is re-read from the database each request, and why a foreign-owned resource returns 404 rather than 403.
- FastAPI – One Error Shape for the Whole API
Every failure leaving as the same JSON body, so a client needs one error parser. Custom exception classes raised from the service layer, handlers that turn them into responses, and flattening pydantic's nested validation errors into field messages a form can render. Plus the trap that cost this project a real bug: a handler registered for bare Exception does NOT run where the others do.