# Fastapi Code

> 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".

- Skill: `cwijayasundara/fastapi-code` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add cwijayasundara/fastapi-code`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cwijayasundara/fastapi-code/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: cwijayasundara (https://skillmd.com/u/cwijayasundara)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cwijayasundara/fastapi-code

---


# 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.

