Belajar FastAPI - Configuration & Environment
Episode 16 of 28

Belajar FastAPI - Configuration & Environment

Merapikan konfigurasi aplikasi dengan pydantic-settings: memindahkan secret ke variabel environment, file .env, kelas Settings bertipe dengan validasi otomatis, hingga pola environment-specific untuk development dan produksi.

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

Pendahuluan

Sejauh ini kita sudah beberapa kali menulis nilai sensitif langsung di kode — SECRET_KEY = "ganti-dengan-secret-kuat" di episode 12, dan DATABASE_URL di episode 9. Di dunia nyata, ini kesalahan fatal: secret di kode = secret yang bocor saat repo di-commit. Episode ini memperbaiki itu semua dengan konfigurasi terpusat.

Mengapa episode ini penting? Aplikasi produksi butuh konfigurasi yang berbeda-beda per environment — database staging vs produksi, secret yang berbeda, fitur yang diaktifkan. Menulis semuanya sebagai konstanta di kode membuat aplikasi tidak bisa dideploy dengan aman. Jawabannya adalah 12-factor app: konfigurasi hidup di environment.

Install pydantic-settings

Install pydantic-settings
pip install pydantic-settings

pydantic-settings memperluas Pydantic untuk membaca konfigurasi dari environment variable dan file .env — dengan validasi dan tipe otomatis.

Kelas Settings Pertama

Pythonapp/config.py
from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )
 
    app_name: str = "FastAPI Lab"
    debug: bool = False
    database_url: str = "sqlite:///./app.db"
    secret_key: str
    access_token_expire_minutes: int = 30
 
 
settings = Settings()

Setiap field kelas adalah setting. Aturan kerjanya:

  • secret_key: str tanpa default → wajib ada di .env atau environment. Jika tidak ada, app gagal start — lebih baik dari pada start dengan secret kosong.
  • database_url: str = "sqlite:///..." → punya default development, bisa di-override di produksi.
  • Pydantic melakukan konversi tipe otomatis: debug: bool membaca "true"/"false" dari string environment jadi boolean.

File .env

Sekarang nilai-nilai kita pindah dari kode ke .env:

.env
APP_NAME=FastAPI Lab
DEBUG=false
DATABASE_URL=postgresql+psycopg://user:password@localhost/appdb
SECRET_KEY=super-rahasia-jangan-di-commit
ACCESS_TOKEN_EXPIRE_MINUTES=30

Penting: .env berisi secret, jadi jangan pernah di-commit ke git. Tambahkan ke .gitignore:

.gitignore
.env
.venv/
__pycache__/
uploads/

Untuk mendokumentasikan variabel yang dibutuhkan tanpa membocorkan nilainya, buat .env.example yang boleh di-commit — ini pola standar tim:

.env.example
DATABASE_URL=
SECRET_KEY=

Important

Prioritas baca pydantic-settings: environment variable > file .env > default di kode. Ini artinya konfigurasi yang di-set di environment (misal di Docker/Kubernetes, episode 24) otomatis menang atas .env. Pola inilah yang membuat satu kode bisa jalan di banyak environment.

Konfigurasi per Environment

Butuh setting berbeda untuk development dan produksi? Tiga pendekatan yang saling melengkapi:

  1. Override via environment — deploy set DATABASE_URL dan SECRET_KEY sebagai env, tanpa mengubah kode.
  2. File .env terpisahSettingsConfigDict(env_file=f".env.{app_env}") untuk .env.dev, .env.prod.
  3. Posisi env — gunakan variabel ENV=development|production di dalam Settings.

Pendekatan 1 adalah yang paling umum dan paling sederhana: kode tetap satu, environment menentukan segalanya. Kita pakai pendekatan ini di episode 24.

Caching Settings

Karena Settings() dipanggil di import, dan konfigurasi tidak berubah saat runtime, instance settings bisa di-share. Di FastAPI, dependency adalah cara idiomatis menyebarkannya:

PythonSettings sebagai dependency
from functools import lru_cache
from typing import Annotated
 
from fastapi import Depends
 
from app.config import Settings
 
 
@lru_cache
def get_settings() -> Settings:
    return Settings()
 
 
SettingsDep = Annotated[Settings, Depends(get_settings)]
 
 
@app.get("/info/")
def app_info(settings: SettingsDep) -> dict[str, str]:
    return {"app_name": settings.app_name, "debug": settings.debug}

@lru_cache memastikan Settings hanya dibuat sekali (hasil di-cache) — dependency ini dipanggil di banyak endpoint tanpa biaya berulang.

Tip

Jangan membuat instance Settings() baru di dalam setiap handler — selain boros, ia juga membuat kode sulit di-test (karena membaca .env sungguhan). Dependency get_settings memberi kalian titik override yang bersih di test — persis pola dependency override di episode 10.

Menyambungkan ke Kode yang Sudah Ada

Ingat SECRET_KEY dan ALGORITHM di episode 12? Sekarang dipindah ke Settings:

Pythonapp/security.py - refactor
import jwt
from app.config import settings
 
 
def create_access_token(subject: str) -> str:
    expire = datetime.now(timezone.utc) + timedelta(
        minutes=settings.access_token_expire_minutes
    )
    payload = {"sub": subject, "exp": expire}
    return jwt.encode(
        payload, settings.secret_key, algorithm="HS256"
    )

Mengganti konstanta dengan settings.xxx membuat seluruh konfigurasi hidup di satu tempat — dan semua perubahan hanya menyentuh .env.

Common Pitfalls

PitfallSolusi
.env ter-commit ke gitTambahkan ke .gitignore; hanya .env.example yang di-commit
Secret tidak wajibSetting tanpa default gagal start jika kosong
Konfigurasi hardcoded di kodePindah semua ke Settings
File .env salah pathCek env_file relatif terhadap working directory
Setting baru tidak terbacaPastikan ada di .env dan nama field cocok

Penutup

Inti yang harus dibawa pulang:

  • pydantic-settings membaca env var, .env, dan default — dengan tipe & validasi.
  • SECRET_KEY, DATABASE_URL, dan kawan-kawan pindah dari kode ke environment.
  • .gitignore untuk .env; .env.example sebagai dokumentasi.
  • Settings sebagai dependency + @lru_cache → satu instance, mudah di-test.

Di episode 17 selanjutnya kita akan membahas logging & error handling — HTTPException yang terstruktur, custom exception handler untuk format error konsisten, serta structured logging yang siap untuk observability. Di sinilah API kalian mulai "dewasa" dan bisa didiagnosis saat produksi bermasalah!

Belajar FastAPI - Configuration & Environment | Belajar FastAPI