Daniel Milewski logoDaniel Milewski
Strona głównaProjektyBlogO mnieKontakt
ENPL
Daniel Milewski logoDaniel Milewski
Strona głównaProjektyBlogO mnieKontaktPolityka prywatności
Kanał RSS

© 2026 Daniel Milewski

JDG (CEIDG) · NIP 8442338935

  1. Strona główna/
  2. Blog/
  3. Wzorce FastAPI, Których Naprawdę Używam w Realnych Projektach

Na tej stronie

Struktura modułów oparta o feature’yDependency injection wszędzie tam, gdzie liczy się testowalnośćAsync SQLAlchemy z jawnym zarządzaniem sesjąUporządkowana obsługa błędówZadania w tle przez ARQ, nie FastAPI `BackgroundTasks`Konfiguracja przez Pydantic Settings
PythonFastAPIBackendArchitektura

Wzorce FastAPI, Których Naprawdę Używam w Realnych Projektach

3 października 2024 · 3 min czytania

Oficjalna dokumentacja FastAPI świetnie nadaje się do startu. Ale między „zrobieniem dema” a „zbudowaniem czegoś, co zespół będzie w stanie utrzymać i rozwijać” jest jeszcze spora luka.

Poniżej są wzorce, których naprawdę używam w produkcyjnych projektach FastAPI.

Struktura modułów oparta o feature’y

Układ warstwowy (routers/, models/, services/) szybko przestaje działać, gdy codebase rośnie. Przy prostej zmianie kończysz grzebiąc w pięciu różnych plikach.

Wolę strukturę opartą o feature’y:

app/
├── auth/
│   ├── router.py
│   ├── service.py
│   ├── models.py
│   └── schemas.py
├── reports/
│   ├── router.py
│   ├── service.py
│   └── schemas.py
└── core/
    ├── config.py
    ├── database.py
    └── dependencies.py

Każdy feature odpowiada za swoje trasy, logikę biznesową, modele bazy i schematy Pydantic. Dodanie nowej funkcji oznacza nowy katalog, a nie rozrzucanie zmian po całym projekcie.

Dependency injection wszędzie tam, gdzie liczy się testowalność

System zależności FastAPI to jedna z jego największych zalet. Warto używać go szeroko:

# core/dependencies.py
async def get_current_user(
    token: str = Depends(oauth2_scheme),
    db: AsyncSession = Depends(get_db),
) -> User:
    ...

# Router feature’a
@router.get("/reports")
async def list_reports(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    ...

W testach podmieniasz zależności na lekkie fake’i działające w pamięci. Dzięki temu testy są szybkie i nie zależą od zewnętrznego stanu.

Async SQLAlchemy z jawnym zarządzaniem sesją

Używaj AsyncSession z SQLAlchemy 2.0 i zarządzaj sesją przez context manager, a nie globalny obiekt:

# core/database.py
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from contextlib import asynccontextmanager

engine = create_async_engine(settings.DATABASE_URL)

@asynccontextmanager
async def get_session() -> AsyncGenerator[AsyncSession, None]:
    async with AsyncSession(engine, expire_on_commit=False) as session:
        try:
            yield session
            await session.commit()
        except Exception:
            await session.rollback()
            raise

expire_on_commit=False zapobiega wygaszaniu obiektów po commit, co w asyncowych kontekstach często powoduje niepotrzebne lazy-loady i dodatkowe zapytania.

Uporządkowana obsługa błędów

Nie dopuszczaj do tego, żeby nieobsłużone wyjątki kończyły się gołym 500 i stack trace’em. Zdefiniuj własną hierarchię błędów:

class AppError(Exception):
    status_code: int = 500
    detail: str = "Internal server error"

class NotFoundError(AppError):
    status_code = 404

class PermissionError(AppError):
    status_code = 403

Zarejestruj handler na instancji aplikacji, który łapie AppError i zwraca spójny JSON. Serwisy rzucają typowane błędy, a routery pozostają czyste.

Zadania w tle przez ARQ, nie FastAPI BackgroundTasks

BackgroundTasks działa w tym samym procesie co aplikacja. Do czegokolwiek większego niż banał, np. generowania raportów, wysyłki maili czy wywołań zewnętrznych API, lepsza jest prawdziwa kolejka zadań.

ARQ (asynchroniczna kolejka Redis) dobrze integruje się z FastAPI:

from arq import create_pool

@router.post("/reports/generate")
async def generate_report(
    report_id: UUID,
    arq_pool: ArqRedis = Depends(get_arq_pool),
):
    await arq_pool.enqueue_job("generate_report_task", report_id)
    return {"status": "queued", "report_id": report_id}

Zadanie działa w osobnym workerze. API może odpowiedzieć od razu, a użytkownik dostaje identyfikator joba do odpytywania albo późniejszego powiadomienia.

Konfiguracja przez Pydantic Settings

pydantic-settings daje typowaną, walidowaną konfigurację opartą o zmienne środowiskowe:

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    DATABASE_URL: str
    SECRET_KEY: str
    OPENAI_API_KEY: str
    REDIS_URL: str = "redis://localhost:6379"
    DEBUG: bool = False

    class Config:
        env_file = ".env"

settings = Settings()

Koniec z rozsianym po projekcie os.getenv("THING", "default"). Konfiguracja jest jawna, typowana i sprawdzana już przy starcie aplikacji.


To nie są rewolucyjne pomysły. To po prostu pragmatyczne decyzje, które sprawdziły się u mnie w kilku wdrożeniach produkcyjnych. Celem jest codebase, który da się zrozumieć, testować i bez bólu przekazać innemu inżynierowi.

Jeśli startujesz nowy projekt w FastAPI i chcesz przegadać architekturę, chętnie pomogę.

Powiązane projekty

InvestTracker — platforma do analityki majątku i portfela inwestycyjnego

Żadne istniejące narzędzie nie potrafiło poprawnie połączyć polskich rachunków inwestycyjnych (IKE, IKZE, OIPE, Finax) z zagranicznymi akcjami, ETF-ami, kryptowalutami i metalami szlachetnymi w jednym, wiarygodnym dashboardzie.

Powiązane wpisy

PythonLLMsProdukcja

Praktyczne Lekcje z Budowania Aplikacji LLM na Produkcji

Demo z LLM-em zrobić łatwo. Produkcyjna aplikacja LLM to zupełnie inna gra. Oto czego nauczyłem się, wdrażając kilka takich systemów naprawdę.

15 listopada 2024 · 3 min czytania

PythonAutomatyzacjaMyślenie produktowe

Co Sprawia, Że Projekty Automatyzacji Naprawdę Dają Wartość Biznesowi

Większość projektów automatyzacji nie przegrywa przez technologię, tylko dlatego, że rozwiązuje zły problem. Oto jak rozpoznać, co naprawdę warto automatyzować.

10 września 2024 · 3 min czytania

Szukasz seniora Python do backendu, API lub automatyzacji?

Ograniczona dostępność na nowe projekty — chętnie o przyszłej współpracy.

Napisz do mnieZobacz projekty
Wszystkie wpisy