Belajar FastAPI - Dependency Injection
Episode 8 of 28

Belajar FastAPI - Dependency Injection

Menguasai dependency injection FastAPI: Depends, sub-dependencies dan chain, class dependencies, dependensi global lewat router dan app, pola Annotated modern, serta dependensi ber-yield untuk manajemen resource.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 7 kita mengendalikan output dengan response_model, sekarang kita membahas fitur yang paling membedakan FastAPI dari framework lain: dependency injection (DI). Di episode 2 kita sudah berkenalan dengan Depends sederhana — sekarang kita buka semua kekuatannya.

Mengapa episode ini penting? Karena DI adalah jawaban FastAPI atas pertanyaan arsitektur yang sering membuat kode berantakan: di mana menaruh logika autentikasi, koneksi database, pagination, atau current user? Jawaban yang buruk: salin-tempel di tiap endpoint. Jawaban FastAPI: dependency — ditulis sekali, dipakai di mana pun, dan bisa diganti saat testing.

Depends: Mekanisme Dasar

Dependency adalah fungsi biasa yang hasilnya di-inject ke handler. FastAPI mengelola siklusnya:

Pythonapp/deps.py
from typing import Annotated
 
from fastapi import Depends, Query
 
 
def pagination_params(
    skip: int = Query(0, ge=0),
    limit: int = Query(10, ge=1, le=100),
) -> dict[str, int]:
    return {"skip": skip, "limit": limit}
 
 
PaginationDep = Annotated[dict[str, int], Depends(pagination_params)]

Dengan Annotated, deklarasi dependency jadi satu alias yang bisa dipakai di banyak endpoint:

Pythonapp/main.py - memakai dependency
from typing import Annotated
from fastapi import FastAPI, Depends
from app.deps import PaginationDep
 
app = FastAPI()
 
Pagination = Annotated[dict[str, int], Depends(pagination_params)]
 
 
@app.get("/items/")
def list_items(pagination: Pagination) -> dict:
    return pagination

Perhatikan keuntungan pola Annotated:

  • Tipe parameter tetap terbaca (dict), metadata tersimpan di Depends.
  • Alias Pagination dipakai berulang tanpa menulis ulang tanda tangan panjang.
  • Bukan lagi masalah urutan parameter (yang di episode 4 bisa menjebak).

Important

Ini gaya yang direkomendasikan dokumentasi FastAPI 0.141: deklarasikan dependency sebagai Annotated[Type, Depends(...)], bukan param: Type = Depends(...). Kode lebih bersih, dan perilaku konsisten saat memakai subclass atau reuse.

Sub-Dependencies: Rantai Dependency

Dependency bisa memanggil dependency lain — FastAPI mengeksekusi seluruh rantai secara otomatis:

PythonSub-dependencies
from typing import Annotated
from fastapi import Depends, FastAPI
 
app = FastAPI()
 
 
def get_prefix() -> str:
    return "item"
 
 
def get_full_prefix(prefix: Annotated[str, Depends(get_prefix)]) -> str:
    return f"{prefix}-v2"
 
 
@app.get("/version/")
def version(full_prefix: Annotated[str, Depends(get_full_prefix)]) -> dict:
    return {"prefix": full_prefix}

FastAPI membangun DAG dependensi: ia mendeteksi get_full_prefix membutuhkan get_prefix, menjalankan get_prefix dulu, lalu menginject hasilnya. Untuk memakai ini, kita pip install python-dotenv... eh, tidak — murni fitur bawaan, tanpa package tambahan.

Class Dependencies

Dependency tidak harus fungsi — class dengan __init__ juga didukung, cocok untuk resource yang perlu inisialisasi:

PythonClass dependency
from typing import Annotated
from fastapi import Depends, FastAPI
 
app = FastAPI()
 
 
class Counter:
    def __init__(self) -> None:
        self.count = 0
 
    def hit(self) -> int:
        self.count += 1
        return self.count
 
 
@app.get("/count/")
def count(counter: Annotated[Counter, Depends()]) -> dict[str, int]:
    return {"count": counter.hit()}

Depends() tanpa argumen memakai class itu sendiri sebagai dependency — FastAPI menginstansiasi Counter dan menginjectnya. Catatan penting: satu instance per request. Dependency FastAPI tidak punya cache antar-request (kecuali di-scope khusus), jadi jangan mengandalkan state antar request.

Global Dependencies

Agar logika tertentu berjalan di semua endpoint, pasang dependency di level router atau app. Ini cara ideal untuk menyisipkan verifikasi API key, logging, atau rate limiting secara global:

PythonGlobal dependency di app
from fastapi import FastAPI, Header, HTTPException
 
app = FastAPI()
 
 
async def verify_api_key(x_api_key: str = Header(...)) -> None:
    if x_api_key != "secret-key":
        raise HTTPException(status_code=401, detail="API key salah")
 
 
app = FastAPI(dependencies=[Depends(verify_api_key)])
 
 
@app.get("/protected/")
def protected() -> dict[str, str]:
    return {"message": "terlindungi"}

dependencies=[...] di konstruktor FastAPI membuat verify_api_key dieksekusi sebelum setiap request — dan tetap muncul sebagai "Security" di dokumentasi OpenAPI. Kita juga bisa menambahkan ke router tertentu (bukan semua app) — ini dibahas saat kita memecah aplikasi di episode 9.

Dependencies dengan yield: Manajemen Resource

yield mengubah dependency menjadi context manager: kode sebelum yield jalan sebelum request, kode setelahnya jalan setelah response dikirim. Ini pola utama untuk koneksi database dan sesi:

PythonDependency dengan yield
from typing import Annotated
from fastapi import Depends, FastAPI
 
app = FastAPI()
 
 
def get_db_session():
    session = "contoh-session"
    try:
        yield session
    finally:
        session = None  # tutup resource di sini
 
 
@app.get("/db/")
def read(session: Annotated[str, Depends(get_db_session)]) -> dict:
    return {"session": session}

finally menjamin pembersihan bahkan saat handler melempar error. Di episode 9, pola ini menjadi rumah bagi sesi SQLAlchemy — dan di episode 10, dependency override-nya menjadi senjata utama testing.

Warning

Dependency dengan yield tidak boleh menangkap HTTPException sebelum yield dan tetap perlu menangani cleanup-nya sendiri. FastAPI akan menyelesaikan dependency generator setelah response selesai — manfaatkan finally untuk menutup koneksi, bukan menaruh cleanup di luar try.

Ringkasan Pola Dependency

PolaSintaksKapan dipakai
Fungsidef fn() -> T + Depends(fn)Logika kecil, query params
Annotated aliasX = Annotated[T, Depends(fn)]Reuse banyak endpoint
Sub-dependencyDepends(other) dalam dependencyLogika bertingkat
ClassDepends() tanpa argumenResource terinisialisasi
GlobalFastAPI(dependencies=[...])Seluruh app / router
yieldyield + finallyManajemen resource (DB)

Penutup

Inti yang harus dibawa pulang:

  • Depends menginject hasil fungsi/class ke handler; FastAPI menyusun rantainya otomatis.
  • Pola Annotated adalah gaya modern yang direkomendasikan FastAPI 0.141.
  • Dependency global (dependencies=[...]) untuk logika lintas app/router.
  • Dependency yield untuk resource lifecycle — fondasi sesi database di episode 9.

Di episode 9 selanjutnya kita akan membangun CRUD lengkap dengan SQLAlchemy — menggabungkan semua yang kita pelajari: Pydantic models untuk schema, dependency untuk sesi database, SQLAlchemy 2.x sebagai ORM, dan Alembic untuk migrasi. Ini episode yang paling banyak ditunggu, karena di sinilah aplikasi FastAPI mulai "hidup" dengan data persisten!

Belajar FastAPI - Dependency Injection | Belajar FastAPI