Dependency Injection in FastAPI with Depends

A
Author
29 Aug, 2026 1 min read 1.52K views

FastAPI's Depends lets endpoints declare what they need (a database session, the current user, pagination settings) and FastAPI provides it. Dependencies can depend on other dependencies, and they're easy to replace in tests.

A simple dependency

from typing import Annotated
from fastapi import Depends, Query

class Pagination:
    def __init__(self, page: int = Query(1, ge=1), size: int = Query(20, ge=1, le=100)):
        self.offset = (page - 1) * size
        self.limit = size

Paging = Annotated[Pagination, Depends()]

@app.get("/articles")
async def list_articles(paging: Paging):
    return await articles.list(offset=paging.offset, limit=paging.limit)

Dependencies with cleanup (yield)

from sqlalchemy.ext.asyncio import AsyncSession

async def get_db():
    async with SessionLocal() as session:
        yield session          # the endpoint runs here
    # session is closed after the response

DbSession = Annotated[AsyncSession, Depends(get_db)]

Chaining: the current user

from fastapi import HTTPException, status
from fastapi.security import OAuth2PasswordBearer

oauth2 = OAuth2PasswordBearer(tokenUrl="/auth/token")

async def get_current_user(token: Annotated[str, Depends(oauth2)], db: DbSession):
    user = await users.from_token(db, token)
    if not user:
        raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
    return user

CurrentUser = Annotated[User, Depends(get_current_user)]

async def require_admin(user: CurrentUser):
    if user.role != "admin":
        raise HTTPException(status.HTTP_403_FORBIDDEN, "Admins only")
    return user

@app.delete("/articles/{article_id}", dependencies=[Depends(require_admin)])
async def delete_article(article_id: int, db: DbSession): ...

Why this design works well

  • Endpoints read like a list of requirements.
  • Within one request, the same dependency is evaluated once and shared.
  • Annotated aliases (DbSession, CurrentUser) keep signatures short.
  • Tests swap implementations with app.dependency_overrides.
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.