2022-02-22 10:00:00+00:00

In high-throughput APIs, managing object lifetimes—such as database connections, external client instances, and memory registries—is critical. Doing this manually inside route handlers creates spaghetti code. FastAPI's built-in dependency injection system provides a clean, declarative solution.

By declaring dependencies, FastAPI automatically handles resource allocation and cleanup at the beginning and end of each request lifecycle.


1. Yielding Asynchronous DB Sessions

For asynchronous databases, we want each request to get its own isolated database transaction session, which is safely committed or rolled back when the request completes. This is achieved using the yield statement:

# Database Session Dependency in FastAPI
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker

DATABASE_URL = "postgresql+asyncpg://postgres:postgres@localhost:5432/postgres"
engine = create_async_engine(DATABASE_URL, pool_size=20, max_overflow=10)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

async def get_db_session():
    async with async_session() as session:
        try:
            yield session
            await session.commit()
        except Exception:
            await session.rollback()
            raise

2. Resolving in Handlers

FastAPI uses Depends() to inject the generated session directly into endpoint parameters. This makes writing tests simple, as mock database connections can override dependency functions effortlessly.