Depends(), it helps to understand what a dependency actually is, why injecting it from outside is better than creating it internally, and how this relates to the Inversion of Control principle. Once those ideas click, Depends() becomes the most natural thing in the world.
What is a Dependency?
A dependency is any object, resource, or service that a function or class needs in order to do its work. In a FastAPI application, your endpoints often depend on things like:- A database session
- A repository or service class
- The currently authenticated user
- Configuration settings
- An external API client
- A logger
A dependency is simply something your code needs to do its job.
What is Dependency Injection?
Dependency Injection (DI) is a design pattern where a function or object receives its dependencies from an external source rather than creating them internally.Without DI — tightly coupled
With DI — loosely coupled
- Loosely coupled — swapping
Printerfor aMockPrinterin tests requires no changes toStudentService - Easier to test — inject a mock or stub at will
- Easier to reuse — the same service works with any compatible printer
What is Inversion of Control?
Inversion of Control (IoC) is a design principle where the responsibility for creating objects and managing application flow is delegated to a framework rather than your own code. Without IoC, your application code creates everything:Is Dependency Injection the same as Inversion of Control?
Is Dependency Injection the same as Inversion of Control?
No. They are related but different concepts.
- IoC is a design principle — it describes who is in control of the application’s workflow and object lifecycle.
- DI is a design pattern — it describes how dependencies are provided to objects.
Is FastAPI already using DI before I use Depends()
Is FastAPI already using DI before I use Depends()
Yes. Even before you use For
Depends(), FastAPI already injects values into your endpoint functions:GET /students/101?active=false, FastAPI automatically injects:student_id = 101(from the path)active = False(from the query string)
Depends() extends this same mechanism to inject higher-level application resources.FastAPI’s Depends()
FastAPI provides a built-in DI system through the Depends() function. When a request arrives, FastAPI:
- Resolves the dependency (calls the provider function)
- Injects the result into the endpoint
- Cleans it up after the request completes (if you use
yield)
Common Dependency Patterns
Database Session Dependency
yield pattern ensures the session is always closed, even if the endpoint raises an exception.
Current User Dependency
Reusable Typed Dependencies with Annotated
Use Annotated to define a reusable dependency alias once and use it everywhere:
Dependency Resolution Flow
get_service() depends on get_db(), FastAPI calls get_db() first, then passes the result to get_service(), then injects the service into your endpoint. You never manage this order manually.
What FastAPI Can Inject
Benefits
UsingDepends() across your application delivers:
- Loose coupling — endpoints don’t know how their dependencies are created
- Testability — override any dependency with a mock in tests using
app.dependency_overrides - Reusability — define a dependency once, inject it in dozens of endpoints
- Automatic lifecycle management —
yielddependencies are always cleaned up - Composability — dependencies can themselves depend on other dependencies