FastAPI
Sources: https://fastapi.tiangolo.com/tutorial/dependencies/, https://fastapi.tiangolo.com/tutorial/testing/, https://fastapi.tiangolo.com/tutorial/background-tasks/, https://fastapi.tiangolo.com/async/, https://pydantic.dev/docs/validation/latest/get-started/migration/ (fetched 2026-07-07 — re-verify if this content seems stale).
Quick Reference
references/dependency-injection-and-validation.md — Depends() patterns (function/class/sub-dependencies), dependency caching per request, Pydantic v2 validation and the v1→v2 migration renames.
references/async-and-testing.md — async def vs def route rules (and what happens when you get it wrong), BackgroundTasks vs a real task queue, TestClient + dependency overrides for testing.
Gotchas (do not skip)
- Blocking code inside
async def blocks the entire server, not just that request — time.sleep() or a synchronous DB call in an async def route stalls every other in-flight request. If a library doesn't support await, use plain def — FastAPI runs it in a threadpool automatically, which is the safe default when unsure.
- Dependencies are cached per request, not globally. The same
Depends(get_db) declared twice in one request's dependency tree executes once and shares the result — but a fresh instance is created on every new request. Don't rely on dependency-level state persisting across requests; use FastAPI's lifespan events for that instead.
Depends(fn) takes the function reference, not a call to it. Depends(get_db), never Depends(get_db()).
- Pydantic v1 method names are gone in v2:
.dict() → .model_dump(), .json() → .model_dump_json(), .parse_obj() → .model_validate(), the inner class Config → a model_config = ConfigDict(...) class attribute, @validator → @field_validator (now requires @classmethod too), @root_validator → @model_validator(mode="before").
TestClient test functions are synchronous (def test_x():, not async def) — no await on client calls, even though the app under test is fully async. Reach for pytest-asyncio only for testing async helper functions directly, not for driving TestClient.
BackgroundTasks runs in the same process, with no persistence or retries. Fine for a quick log write or notification; a crash before it completes loses the task silently. Reach for a real task queue (Celery + Redis/RabbitMQ) when the work is heavy, must survive a crash, or needs distributed execution.
Not Yet Covered Here (fetch before relying on these topics)
Database/ORM patterns (SQLAlchemy) are explicitly out of scope for this skill — see the design's own scoping decision. If a project needs that content, fetch https://docs.sqlalchemy.org/ fresh rather than guessing.
1---2name: fastapi-code3description: Build FastAPI backends — dependency injection with Depends(), Pydantic v2 request/response validation, async vs sync route rules, background tasks, and testing with TestClient. Use for any FastAPI route, dependency, or Pydantic model. Not for database/ORM design (no SQLAlchemy content here) or non-FastAPI Python web frameworks. Triggers on "FastAPI route", "Depends()", "Pydantic model", "FastAPI dependency", "FastAPI testing", "TestClient", "async def vs def FastAPI".4---56# FastAPI78Sources: https://fastapi.tiangolo.com/tutorial/dependencies/, https://fastapi.tiangolo.com/tutorial/testing/, https://fastapi.tiangolo.com/tutorial/background-tasks/, https://fastapi.tiangolo.com/async/, https://pydantic.dev/docs/validation/latest/get-started/migration/ (fetched 2026-07-07 — re-verify if this content seems stale).910## Quick Reference1112- `references/dependency-injection-and-validation.md` — `Depends()` patterns (function/class/sub-dependencies), dependency caching per request, Pydantic v2 validation and the v1→v2 migration renames.13- `references/async-and-testing.md` — `async def` vs `def` route rules (and what happens when you get it wrong), `BackgroundTasks` vs a real task queue, `TestClient` + dependency overrides for testing.1415## Gotchas (do not skip)1617- **Blocking code inside `async def` blocks the entire server**, not just that request — `time.sleep()` or a synchronous DB call in an `async def` route stalls every other in-flight request. If a library doesn't support `await`, use plain `def` — FastAPI runs it in a threadpool automatically, which is the *safe default* when unsure.18- **Dependencies are cached per request, not globally.** The same `Depends(get_db)` declared twice in one request's dependency tree executes once and shares the result — but a fresh instance is created on every new request. Don't rely on dependency-level state persisting across requests; use FastAPI's lifespan events for that instead.19- **`Depends(fn)` takes the function reference, not a call to it.** `Depends(get_db)`, never `Depends(get_db())`.20- **Pydantic v1 method names are gone in v2**: `.dict()` → `.model_dump()`, `.json()` → `.model_dump_json()`, `.parse_obj()` → `.model_validate()`, the inner `class Config` → a `model_config = ConfigDict(...)` class attribute, `@validator` → `@field_validator` (now requires `@classmethod` too), `@root_validator` → `@model_validator(mode="before")`.21- **`TestClient` test functions are synchronous** (`def test_x():`, not `async def`) — no `await` on client calls, even though the app under test is fully async. Reach for `pytest-asyncio` only for testing async helper functions directly, not for driving `TestClient`.22- **`BackgroundTasks` runs in the same process, with no persistence or retries.** Fine for a quick log write or notification; a crash before it completes loses the task silently. Reach for a real task queue (Celery + Redis/RabbitMQ) when the work is heavy, must survive a crash, or needs distributed execution.2324## Not Yet Covered Here (fetch before relying on these topics)2526Database/ORM patterns (SQLAlchemy) are explicitly out of scope for this skill — see the design's own scoping decision. If a project needs that content, fetch `https://docs.sqlalchemy.org/` fresh rather than guessing.