How to Implement Dependency Injection in FastAPI

How to Implement Dependency Injection in FastAPI
# Understanding Dependency Injection in FastAPI

Several languages and frameworks rely heavily on **dependency injection** — no pun intended. Go, Angular, NestJS, and Python's **FastAPI** all use it as a core architectural pattern.

If you've worked with FastAPI, you've likely encountered dependencies in action. Maybe you’ve seen `Depends()` in a tutorial or the official documentation and felt confused — I certainly did at first. That confusion led to weeks of experimenting with FastAPI's dependency system.

The truth is: **dependency injection in FastAPI is unavoidable** when building backend services. It’s embedded into the framework’s core, powering functionalities such as:

- Authentication
- Database connections
- Request validation

FastAPI’s documentation describes its DI system as *“powerful but intuitive”*. Once you understand the fundamentals, that’s spot on.

This article breaks it down into:

- Function-based dependencies
- Class-based dependencies
- Dependency scopes
- Practical usage examples

---

## Table of Contents

- [Prerequisites](#prerequisites)
- [Dependencies and Dependency Injection in FastAPI](#dependencies-and-dependency-injection-in-fastapi)
- [Getting Started: Environment Setup](#getting-started-environment-setup)
- [Types of Dependencies in FastAPI](#types-of-dependencies-in-fastapi)
  - [Function Dependencies](#function-dependencies)
  - [Class Dependencies](#class-dependencies)
- [Dependency Scope](#dependency-scope)
  - [Path Operation Level](#path-operation-level)
  - [Router Level](#router-level)
  - [Application Level](#application-level)
- [Common Use Cases](#common-use-cases)
- [Conclusion](#conclusion)

---

## Prerequisites

You should have:

- Working knowledge of **Python**
- Ability to create and activate **virtual environments**
- Basic understanding of **FastAPI**
- Familiarity with **OOP** concepts

---

## Dependencies and Dependency Injection in FastAPI

### What’s a Dependency?
A **dependency** is reusable logic that your path operations can require — for example, authentication, DB connection, or validation.

### What’s Dependency Injection?
**Dependency injection (DI)** is the mechanism FastAPI uses to provide these dependencies to the parts of the app where they’re needed.

You declare them using `Depends()`, and FastAPI automatically executes them before running the endpoint.

**Benefits**:
- Avoids repetitive setup code in each route
- Keeps applications **modular** and **scalable**
- Reduces bugs and maintenance overhead

---

## Getting Started: Environment Setup

1. **Create & activate a virtual environment**:

python -m venv deps

source deps/bin/activate # macOS / Linux

deps\Scripts\activate # Windows


2. **Install FastAPI**:

pip install 'fastapi[all]'


3. **Organize your project structure**:

project/

├── main.py

├── deps/

│ └── __init__.py


---

## Types of Dependencies in FastAPI

A dependency can be any **callable object** that performs checks or retrieves data before an endpoint runs.

- **Function Dependencies** — Simple, ideal for most cases: validation, auth, data fetch
- **Class Dependencies** — Useful when you need state, OOP patterns, or multiple configurations

---

## Function Dependencies

The easiest method is defining a helper function.  

Example: In `fastapi-deps/function_deps.py`:

### Step 1: Imports

from fastapi import FastAPI, Depends, HTTPException

import uvicorn


### Step 2: Create Application

app = FastAPI()


### Step 3: In-Memory Database

users = [

{"name": "Ore", "password": "jkzvdgwya12"},

{"name": "Uche", "password": "lga546"},

{"name": "Seke", "password": "SK99!"},

# ...

]


**Note:** This storage is non-persistent. Data is lost on restart.

### Step 4: Dependency Function

def user_dep(name: str, password: str):

for u in users:

if u["name"] == name and u["password"] == password:

return {"name": name, "valid": True}


### Step 5: Inject Dependency into Route

@app.get("/users/{user}")

def get_user(user = Depends(user_dep)) -> dict:

if not user:

raise HTTPException(status_code=401, detail="Invalid username or password")

return user


---

### Start & Test the Server

uvicorn function_deps:app --reload


Test in browser/Postman:

http://127.0.0.1:8000/users/{user}?name=Seke&password=SK99!


Or via Swagger docs:

http://127.0.0.1:8000/docs


---

## Class Dependencies

Ideal for **stateful** logic or complex initializations.

### Authentication Class Example

class UserAuth:

def __init__(self, name: str, password: str):

self.name = name

self.password = password

def __call__(self):

for user in users:

if user["name"] == self.name and user["password"] == self.password:

return

raise HTTPException(status_code=401, detail="Invalid username or password")


### Use in Route

@app.get("/user/dashboard")

def get_dashboard(user: UserAuth = Depends(UserAuth)):

return {"message": f"Access granted to {user.name}"}


---

## Dependency Scope

FastAPI allows injecting dependencies on different levels:

1. **Path Operation Level**
2. **Router Level**
3. **Application Level**

---

### Path Operation Level

def user_dep(name: str, password: str):

for u in users:

if u["name"] == name and u["password"] == password:

return

raise HTTPException(status_code=401, detail="Invalid username or password")

@app.get("/users/{user}", dependencies=[Depends(user_dep)])

def get_user() -> dict:

return {"message": "Access granted!"}


The dependency runs **before** the endpoint but **does not** pass its return value.

---

### Router Level

`fastapi-deps/router_deps.py`:

from fastapi import APIRouter, Depends

from function_deps import user_dep

router = APIRouter(prefix="/users", dependencies=[Depends(user_dep)])

@router.get("/{user}")

def get_user() -> dict:

return {"message": "Access granted!"}


`app.py`:

from fastapi import FastAPI

from router_deps import router as user_router

import uvicorn

app = FastAPI()

app.include_router(user_router)

if __name__ == "__main__":

uvicorn.run("app:app", reload=True)


---

### Application Level

Global dependencies run on **every** route.

from fastapi import FastAPI, Depends

from function_deps import user_dep

from router_deps import router as user_router

from datetime import datetime

import uvicorn

def log_request():

print(f"[{datetime.now()}] Request received.")

app = FastAPI(dependencies=[Depends(log_request), Depends(user_dep)])

app.include_router(user_router)

@app.get("/home")

def get_main():

return "Welcome back!!!"

if __name__ == "__main__":

uvicorn.run("app:app", reload=True)


---

## Common Use Cases

- **Database connections** — Avoid connection leaks
- **Auth & authorization** — Token validation, role checking
- **Logging & monitoring**
- **Rate limiting**
- **Config injection** — Environment variables, API keys
- **Pagination/filtering** — Shared query parameter logic

---

## Conclusion

FastAPI’s DI system enables **clean**, **reusable**, and **maintainable** code.  
While not necessary for simple one-off logic, DI shines when managing shared logic, lifecycles, and modular designs.

It reduces repetition, centralizes logic, and improves scalability — making it a key part of any serious FastAPI project.

Read more

Translate the following blog post title into English, concise and natural. Return plain text only without quotes. 哈佛大学 R 编程课程介绍

Harvard CS50: Introduction to Programming with R Harvard University offers exceptional beginner-friendly computer science courses. We’re excited to announce the release of Harvard CS50’s Introduction to Programming in R, a powerful language widely used for statistical computing, data science, and graphics. This course was developed by Carter Zenke.