lesson depth
Mastery
not started · 0%

FastAPI Dependency Injection

Request-scoped dependencies, yield cleanup generators, and test overrides.

Freshness: current15 min readSoftware and Web Engineering

Key Learning Outcomes

  • Build hierarchical dependency DAGs
  • Manage connection lifespans and mocks

Mental model

FastAPI's dependency injection engine constructs a Directed Acyclic Graph (DAG) of dependencies per HTTP request, solving requirements, managing resource scope, and closing yield generators upon request completion.

Incoming HTTP Request
Resolve Dependency DAG
Execute Yield Setup
Inject Resource into Endpoint
Teardown Yield Cleanup
Conceptual teaching model synthesized from:FastAPI Framework Architecture & Dependency Injection Specification

Theory

Dependencies declared with Depends(func) can be nested arbitrarily deep. When a dependency uses yield instead of return, FastAPI executes code before yield prior to route handler execution, injects the yielded value, and executes code after yield during response cleanup (even if an exception occurs).

python(23 lines)
1from typing import AsyncGenerator
2from fastapi import FastAPI, Depends
3from contextlib import asynccontextmanager
4
5@asynccontextmanager
6async def lifespan(app: FastAPI):
7 app.state.db = {"active": True}
8 yield
9 app.state.db["active"] = False
10
11app = FastAPI(lifespan=lifespan)
12
13async def get_db_session() -> AsyncGenerator[dict, None]:
14 session = {"session_id": "tx_9942", "db": app.state.db}
15 try:
16 yield session
17 finally:
18 session["closed"] = True
19
20@app.get("/items")
21async def read_items(db=Depends(get_db_session)):
22 return {"status": "ok", "session": db["session_id"]}

Alternatives and trade-offs

Manual dependency instantiation leads to code duplication and tight coupling. FastAPI's app.dependency_overrides allows swapping real databases for in-memory mocks during Pytest runs seamlessly.

Failure modes and misconceptions

  1. Leaking resources without finally: Failing to wrap yield cleanup in try...finally leaves database sessions unclosed if route handlers raise uncaught exceptions.
  2. Global state mutation: Modifying global dependency state across concurrent requests causes race conditions.
Reflect before revealing the guide

Decision scenario

Use asynccontextmanager lifespans for global application resource pools (database pools, Redis clients). Use Depends with yield generators for per-request session isolation.

Learning outcomes

  • Build composable dependency DAGs in FastAPI routes.
  • Implement lifespan context managers for application lifecycle state.
  • Swap production dependencies with test doubles via dependency_overrides.

Trade-offs

FastAPI dependency injection simplifies composition and testing, but complex nested dependency graphs can make execution order harder to trace without clear logging.

Prerequisites & Related Concepts (2)

Private notes

0 words
Next