Muhammad Ahmad Faizan
Back to Notes
FastAPIPythonBackendArchitecture

FastAPI Production Patterns

2025-10-17

FastAPI Production Patterns

FastAPI is my default framework for Python APIs. Here are the patterns I use in every production deployment.

Dependency Injection for Services

FastAPI's Depends() system is more powerful than most people use. I wire all external services (database, LLM providers, cache) through dependency injection:

async def get_db() -> AsyncSession:

async with async_session() as session:

yield session

async def get_llm() -> LLMProvider:

return LLMProvider()

@app.post("/query")

async def query(

request: QueryRequest,

db: AsyncSession = Depends(get_db),

llm: LLMProvider = Depends(get_llm),

):

...

This makes testing trivial — just override the dependencies with mocks.

Background Tasks with Lifespan

For long-running AI tasks, I use FastAPI's BackgroundTasks combined with the lifespan pattern for startup/shutdown:

@asynccontextmanager

async def lifespan(app: FastAPI):

# Startup: initialize connection pools, load models

app.state.model = await load_model()

yield

# Shutdown: clean up resources

await app.state.model.close()

Structured Logging

Don't use print() or basic logging. Use structlog or a JSON-based logger that captures request IDs, latency, and error context. Every log line should be traceable to a specific request.

Database Sessions

Use async sessions with SQLAlchemy 2.0's async engine. Never share sessions across requests. Always use session-per-request pattern with dependency injection.

The combination of these patterns produces APIs that are testable, observable, and maintainable at scale.