Skip to content

Dependency Injection

FastAPI's Depends() system is the backbone of the application. Every service, repository, and cross-cutting concern flows through it.

Database Session

from collections.abc import AsyncGenerator
from sqlalchemy.ext.asyncio import AsyncSession


async def get_db() -> AsyncGenerator[AsyncSession, None]:
    async with async_session_maker() as session:
        yield session

Repository and Service Dependencies

Chain dependencies to build the full layer stack:

from fastapi import Depends


async def get_user_repository(
    db: AsyncSession = Depends(get_db),
) -> UserRepository:
    return UserRepository(db)


async def get_user_service(
    repo: UserRepository = Depends(get_user_repository),
    event_bus: EventBus = Depends(get_event_bus),
) -> UserService:
    return UserService(repo=repo, event_bus=event_bus)

Routes then declare the service they need:

@router.get("/users/{user_id}", response_model=UserResponse)
async def get_user(
    user_id: UUID,
    service: UserService = Depends(get_user_service),
) -> UserResponse:
    return await service.get_user(user_id)

Parameterized Dependencies

Use closures for configurable dependencies like permission checks:

def requires_permission(permission: str):
    async def dependency(
        current_user: User = Depends(get_current_active_user),
    ) -> User:
        if not current_user.has_permission(permission):
            raise ForbiddenError(f"Missing permission: {permission}")
        return current_user
    return dependency


@router.delete("/users/{user_id}", status_code=204)
async def delete_user(
    user_id: UUID,
    service: UserService = Depends(get_user_service),
    _: User = Depends(requires_permission("users:delete")),
):
    await service.delete_user(user_id)

When to Use Depends

Scenario Use Depends() Use direct instantiation
Database sessions Yes Never
Repositories and services Yes Never
Auth / current user Yes Never
Configuration values Yes (via Settings) For constants
Utility functions with no I/O No Yes

See Also