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.