Skip to content

Repository files navigation

Clean Architecture FastAPI Starter Kit

Production-oriented starter kit built with FastAPI + async SQLAlchemy, structured around a Clean Architecture / DDD-inspired layering model.

It is designed like a Django-style startproject baseline: a ready-to-extend foundation with real modules (auth/users/groups/permissions), explicit use-case orchestration, dependency injection, and production-minded defaults.


Overview

Production-oriented FastAPI starter kit implementing:

  • Clean Architecture / DDD-inspired layering
  • JWT authentication + RBAC authorization
  • Async SQLAlchemy + PostgreSQL
  • Dependency Injection
  • Dockerized development workflow
  • CI/CD pipelines and quality gates

Designed as a scalable backend foundation instead of a simple CRUD example.


Why This Starter Kit Exists

Most CRUD backends become hard to evolve because business logic gets mixed with framework and database details.
This starter kit demonstrates how to keep boundaries explicit from day one:

  • Business rules live in domain
  • Application workflows live in application/use_cases
  • Infrastructure adapters (DB/security) live in infrastructure
  • HTTP/API concerns live in presentation

Result: easier testing, clearer dependencies, and safer long-term refactoring.


What This Starter Kit Includes

Out of the box modules:

  • Authentication
    • POST /v1/auth/login
  • Users
    • GET /v1/users/
    • GET /v1/users/{user_id}
    • POST /v1/users/
    • PATCH /v1/users/{user_id}
    • DELETE /v1/users/{user_id}
  • Groups
    • GET /v1/groups/
    • POST /v1/groups/
    • DELETE /v1/groups/{group_id}
  • Permissions
    • GET /v1/permissions/
  • RBAC operations
    • assign/remove permission to/from group
    • add/remove user to/from group
    • under /v1/rbac/groups/{group_id}/...

Route composition is defined in src/presentation/api/v1/routes.py.


Architecture At a Glance

Client
  -> FastAPI app (src/main.py, src/core/app.py)
    -> Presentation layer (endpoints/schemas/dependencies)
      -> Application layer (use cases)
        -> Domain contracts (ports/repositories/entities)
          <- Infrastructure implementations (UoW, repositories, security services)
            -> PostgreSQL (SQLAlchemy async)

Layer Responsibilities

  • Domain (src/domain)

    • Core entities: User, Group, Permission
    • Domain exceptions and enums
    • Repository/port contracts
    • RBAC permission definitions (src/domain/rbac/permissions.py)
  • Application (src/application)

    • Use cases for auth/users/groups/permissions/RBAC
    • DTOs (src/application/dtos)
    • Coordinates domain rules with ports (without HTTP or ORM coupling)
  • Infrastructure (src/infrastructure)

    • Async PostgreSQL connection
    • SQLAlchemy models/repositories
    • Unit of Work implementation
    • JWT service + password hashing
    • DI container wiring (src/infrastructure/container.py)
  • Presentation (src/presentation)

    • FastAPI endpoints
    • Request/response schemas
    • Authentication and authorization dependencies
    • Middleware + exception translation to HTTP responses
  • Core (src/core)

    • App factory
    • Environment-driven configuration
    • Structured logging bootstrap

Request Lifecycle (Real Example)

Login (POST /v1/auth/login)

  1. Endpoint receives LoginRequest (src/presentation/api/v1/endpoints/authentication.py)
  2. LoginUseCase is resolved from DI container
  3. Use case loads user from repository via UoW
  4. Password is verified with PasswordHasher
  5. JWTService creates access/refresh tokens
  6. Response returns token pair

Protected endpoint (GET /v1/users/)

  1. HTTPBearer extracts token (src/presentation/dependencies/auth_dep.py)
  2. GetCurrentUserUseCase validates/decode JWT and loads user
  3. Permission dependency checks codename via CheckUserPermissionUseCase
  4. User list use case fetches data through repository
  5. Response schema maps domain objects to API contract

Security Model

  • Authentication: JWT access/refresh tokens (src/infrastructure/security/jwt_service.py)
  • Password storage: bcrypt/passlib hashing (src/infrastructure/security/password_hasher.py)
  • Authorization: endpoint-level RBAC dependency (require_permission(...))
  • Permission source: group-permission associations + superuser bypass in domain entity logic
  • Error handling: centralized exception mapping with consistent error payloads
  • Request observability: request-id middleware for trace-friendly logs

Tech Stack

  • Python 3.12
  • FastAPI
  • SQLAlchemy 2 (async)
  • asyncpg
  • Pydantic v2 + pydantic-settings
  • dependency-injector
  • PyJWT + passlib + bcrypt
  • Alembic
  • pytest / pytest-asyncio
  • Ruff / pre-commit
  • Docker + Docker Compose + Nginx

Dependency pins are in:

  • dev.requirements.txt
  • prod.requirements.txt

Architecture Decisions

The why behind the major choices (layering, DI, UoW, JWT strategy, RBAC registry, exception contract, logging) lives as ADRs:

  • docs/adr/ — Architecture Decision Records (MADR format)

Repository Structure

src/
  core/                     # app factory, config, logging
  domain/                   # entities, contracts, business rules
  application/              # use cases + DTOs
  infrastructure/           # DB/security adapters + DI container
  presentation/             # API endpoints/schemas/dependencies/middlewares
  main.py                   # ASGI entrypoint

alembic/                    # migrations
tests/                      # unit + integration tests
scripts/                    # operational scripts (RBAC seed, superuser creation)
docker/                     # Dockerfiles
docs/                       # API + architecture notes
.github/workflows/          # CI/CD pipelines

Local Development

1) Prerequisites

  • Python 3.12+
  • Docker / Docker Compose (recommended)
  • PostgreSQL (if running without Docker)

2) Install dependencies

python -m venv .venv
# Linux/macOS
source .venv/bin/activate
# Windows (PowerShell)
# .venv\Scripts\Activate.ps1

pip install -r dev.requirements.txt

3) Configure environment

This project reads env from .env.dev when APP_ENV=dev.

Minimum keys:

APP_ENV=dev

DATABASE_NAME=auth_db
DATABASE_USER=postgres
DATABASE_PASSWORD=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432

SERVICE_NAME=auth-service
SERVICE_HOST=0.0.0.0
SERVICE_PORT=8000
OPENAPI_URL=/openapi.json

SECRET_KEY=change-me
ALGORITHM=HS256
ACCESS_TOKEN_LIFETIME_DAYS=1
REFRESH_TOKEN_LIFETIME_DAYS=7

4) Run with Docker Compose

docker compose up --build

Services:

  • PostgreSQL
  • Backend (uvicorn src.main:app ...)
  • Nginx reverse proxy

5) Run without Docker

uvicorn src.main:app --reload

API docs (custom Swagger path):

  • http://localhost:8000/my-swagger

Health endpoint:

  • GET /health

Database and Migrations

  • SQLAlchemy models are under src/infrastructure/database/postgresql/models
  • Alembic config: alembic.ini, alembic/env.py

Common commands:

alembic upgrade head
alembic revision --autogenerate -m "describe change"
alembic downgrade -1

Bootstrapping Starter Data

Seed permission catalog and admin group:

python scripts/seed_rbac.py

Create a superuser interactively:

python scripts/create_superuser.py

Testing and Quality Gates

Run tests:

pytest tests/

Coverage:

pytest tests/ --cov=src --cov-report=term --cov-report=xml

Lint:

ruff check src/

Pre-commit hooks:

pre-commit install
pre-commit run --all-files

CI pipeline (.github/workflows/ci.yml) runs:

  • lint
  • tests + coverage artifact
  • docker build
  • security scans (Trivy, Bandit, Safety)

Deployment Notes

The repository includes a Docker-based CD workflow (.github/workflows/cd.yml) that:

  • builds and validates an image
  • transfers it to a remote server
  • runs the container over SSH

This reflects an end-to-end deployment mindset, including image packaging and remote rollout automation.


Engineering Topics Demonstrated

This project showcases practical experience in:

  • Layered backend architecture (Clean Architecture style)
  • Dependency injection and explicit wiring of use cases
  • Async API and persistence design
  • Repository + Unit of Work patterns
  • JWT authentication and RBAC authorization
  • Domain-driven module boundaries
  • Structured exception contracts
  • Logging and request correlation
  • Containerized local/dev workflow
  • CI quality gates and security scanning
  • Migration-driven schema evolution

Current Scope and Improvement Opportunities

The current implementation already provides a strong architecture baseline.
Natural next steps for production hardening:

  • align migrations and runtime table-creation strategy
  • expand integration coverage for groups/permissions/RBAC paths
  • tighten CI/CD Dockerfile/env consistency

These are engineering refinements, not blockers for understanding the architecture.


Author

Esmaeil Taheri

About

Production-oriented starter kit built with FastAPI + async SQLAlchemy, structured around a Clean Architecture / DDD-inspired layering model.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages