FastAPI: From Basics to Production · Dependency Injection in Depth
Dependencies, Sub-dependencies and Classes
Compose reusable request logic with Depends.
A dependency is any callable (function or class) that FastAPI calls before your endpoint, resolving its own parameters (query, headers, other dependencies). Dependencies form a graph: get_current_user depends on get_token which depends on a header. Classes work as dependencies too (Depends() with no argument uses the annotated class). Dependencies can be attached to routers or the whole app for cross-cutting checks.
from typing import Annotated
from fastapi import APIRouter, Depends, Header, HTTPException
async def get_token(authorization: Annotated[str | None, Header()] = None) -> str:
if not authorization or not authorization.startswith("Bearer "):
raise HTTPException(401, "Missing bearer token", headers={"WWW-Authenticate": "Bearer"})
return authorization.removeprefix("Bearer ")
async def get_current_user(token: Annotated[str, Depends(get_token)], db: DB) -> User:
return await auth.user_from_token(db, token)
CurrentUser = Annotated[User, Depends(get_current_user)]
async def require_verified(user: CurrentUser) -> None:
if not user.email_verified:
raise HTTPException(403, "Verify your email first")
router = APIRouter(prefix="/billing", dependencies=[Depends(require_verified)])
Common pitfalls
- Business logic inside dependencies that should live in services.
- Raising generic exceptions instead of HTTPException in auth dependencies.
- Forgetting dependencies are cached per request (usually desirable).
Key points
- Dependencies form a graph
- Router/app-level dependencies for cross-cutting checks
- Annotated aliases like CurrentUser
Further reading: FastAPI: Sub-dependencies
Practice questions
How do you require a check on every route in a router without changing each endpoint?
Answer
Pass dependencies=[Depends(check)] to APIRouter(...) (or include_router), so it runs for all routes; its return value isn't injected.
Can a class be a dependency?
Answer
Yes. FastAPI calls the class like a function, resolving its __init__ parameters, and injects the instance — useful for parameter groups like pagination.
Open in the app to mark lessons complete, take notes and track your progress.