Skip to content

The Superpower: Dependency Injection

Dependency Injection (DI) system is widely considered FastAPI’s most powerful and useful feature. In software engineering, DI is a design pattern that allows a program to remove hard-coded dependencies and make it possible to change them, often to facilitate testing.

In many frameworks (like Java’s Spring), DI can be complex and verbose. FastAPI makes it incredibly simple. You don’t need to create classes or register containers. In FastAPI, a dependency is just a function (or a class) that provides data or logic to your path operations.

Imagine you have query parameters for pagination (skip and limit) that you use in many different endpoints. Instead of rewriting the arguments in every path operation, you can define them once in a function.

from typing import Annotated
from fastapi import Depends, FastAPI
app = FastAPI()
# 1. Create the dependency function
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
# 2. Inject it into the path operation
@app.get("/items/")
async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
return commons
@app.get("/users/")
async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
return commons

When a request hits /items/, FastAPI sees the Depends(common_parameters):

  • It calls common_parameters.
  • It passes the query parameters (q, skip, limit) to that function.
  • It takes the result returned by common_parameters.
  • It assigns that result to the commons parameter in your path operation.

FastAPI allows you to build graphs of dependencies. A dependency function can itself use Depends to require other dependencies.

For example, you might have a dependency get_token that extracts a header. Then, a dependency get_user that depends on get_token to find the user. Finally, your path operation depends on get_user. FastAPI handles this entire chain automatically.

Sometimes you need to perform an action after the request has been processed, such as closing a database connection or a file. FastAPI supports this via the yield keyword.

This is very similar to Python’s Context Managers (with statements). The code before yield runs before the request processing, and the code after yield runs after the response is sent.

async def get_db():
db = DBSession()
try:
yield db
finally:
# This runs after the request is finished
db.close()

By using yield, you ensure that resources are properly cleaned up, even if an exception occurs during the request processing.