Skip to content

Subhransu-De/FastAPI-Template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

131 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FastAPI Template

SonarQube Quality Gate SonarCloud Bugs SonarCloud Vulnerabilities SonarCloud Code Smells Snyk Repository CI/CD

FastAPI Python Pydantic SQLAlchemy PostgreSQL

A production-minded FastAPI starter that gives you a clean async API, a real database path, authentication, observability, CI checks, and multiple test layers from day one.

What It Contains

Area Included
API FastAPI application with health endpoints and protected CRUD routes for entities.
Database PostgreSQL, SQLAlchemy async sessions, Psycopg, and Alembic migrations run as a one-shot startup task before the API starts.
Authentication OAuth2 authorization-code flow, JWT bearer validation, and a Keycloak-backed Docker setup.
Validation and settings Pydantic v2 schemas and pydantic-settings based application, database, and auth configuration.
Observability Structured logging plus Logfire/OpenTelemetry instrumentation for FastAPI and SQLAlchemy.
Local runtime Docker Compose stack for the API, PostgreSQL, and Keycloak.
Quality gates Ruff linting, Ty type checks, import-linter architecture checks, coverage enforcement, SonarCloud analysis, and Snyk security status.
Dependency upkeep Dependabot is configured for Python, Docker, Docker Compose, and GitHub Actions updates.

Testing Strategy

This template keeps tests split by purpose so each feedback loop stays clear:

  • Unit tests cover isolated settings, auth, service, IO, logging, and exception behavior.
  • Integration tests exercise the API and repository with disposable PostgreSQL through Testcontainers.
  • Scenario tests live in scenario-tests and use Behave plus HTTPX against the running Docker Compose stack.
  • Coverage checks run with pytest-cov; CI currently enforces at least 80% coverage.
  • Mutation testing is configured for auth, IO, service, and repository modules, but kept outside the normal PR gate.

Architecture

At a glance, the template wires requests, authentication, business behavior, persistence, migrations, and scenario tests like this:

flowchart LR
    client["Client / API consumer"] -->|"HTTP"| routes["app/routes<br/>FastAPI routers"]
    scenario["scenario-tests<br/>Behave + HTTPX"] -->|"HTTP against running stack"| routes

    routes -->|"Depends"| auth["app/auth<br/>OAuth2 + JWT validation"]
    keycloak["Keycloak<br/>OIDC issuer"] -->|"Tokens + JWKS"| auth

    routes -->|"Pydantic input/output"| io["app/io<br/>Request and response schemas"]
    routes -->|"Depends"| service["app/service<br/>Business behavior"]
    service --> repository["app/repository<br/>Async data access"]
    repository --> database["app/database<br/>Engine and sessions"]
    model["app/model<br/>SQLAlchemy models"] --> repository
    database --> postgres[("PostgreSQL")]

    compose["Docker Compose<br/>startup order"] --> alembic["migrate service<br/>Alembic upgrade head"]
    alembic --> postgres
    alembic --> main["app/main.py<br/>Application startup"]

    settings["app/settings<br/>Environment configuration"] -.-> routes
    settings -.-> database
    settings -.-> auth

Loading

The application uses a small layered architecture:

  • app/routes owns HTTP endpoints, request dependencies, and route grouping.
  • app/service holds business behavior and coordinates repository calls.
  • app/repository isolates persistence logic behind reusable async repository helpers.
  • app/model defines SQLAlchemy database models.
  • app/io defines request and response schemas at the API boundary.
  • app/settings, app/auth, and app/logger keep cross-cutting concerns separate from endpoint logic.

This shape is meant for teams that want a practical backend template: simple enough to understand quickly, but structured enough to grow into a real service without immediately rewriting the foundation.

Installation

uv sync
cp .env.example .env

Fill in the required values in .env before starting the app.

Running the Application

Development mode:

make run

make run applies alembic upgrade head with the migration dependency group, then starts the FastAPI app.

Docker-based development:

docker compose up --build

Docker Compose builds the API from Dockerfile and the one-shot migration service from Dockerfile.migration. Their default image tags include COMPOSE_PROJECT_NAME, so parallel worktrees do not overwrite each other's local images; APP_IMAGE and MIGRATION_IMAGE can still override those tags. Compose starts migrate first, waits for alembic upgrade head to exit successfully, and then starts the API container. If migrations fail, the API container does not start.

Swagger UI signs users in with the public fastapi-docs client using authorization code flow plus PKCE. The API continues to validate the fastapi-client audience. A browser client must never receive a client secret; OIDC_CLIENT_SECRET is used only by the confidential client in scenario tests.

Compose does not assign host-global container names. To run isolated stacks in parallel, give each one a unique project name, application port, Keycloak port, and public URLs:

COMPOSE_PROJECT_NAME=fastapi-feature-a \
APP_PORT=8081 \
APP_PUBLIC_URL=http://localhost:8081 \
KEYCLOAK_PORT=8181 \
OIDC_PUBLIC_URL=http://localhost:8181 \
docker compose up --build

The keycloak-config one-shot service registers the exact Swagger callback for APP_PUBLIC_URL; production deployments should likewise use exact redirect URIs rather than wildcards.

Customizing the Template

When adopting this repository, update the application name, package metadata, image names, OIDC realm/client identifiers, and Sonar/Snyk project identifiers. Compose service names such as db and keycloak are internal DNS names and do not need to be renamed for stack isolation.

Container Images and Production Migrations

Build and push both images before deployment:

  • API image: built from Dockerfile; default command is python -m app.main; installs only application runtime dependencies.
  • Migration image: built from Dockerfile.migration; default command is alembic -c alembic.ini upgrade head; installs only the migration dependency group and only ships the Alembic migration files.

For ECS, run the migration image as a one-off task before updating or starting the service. For EKS, run the migration image as a Kubernetes Job before rolling out the Deployment. In both cases, the migration task/job must use the same production database environment variables as the application release.

Testing

Run the default test suite:

make test

Run tests with coverage:

make test-cov

Run scenario tests against the e2e Docker Compose stack:

export COMPOSE_FILE=docker-compose.yml:docker-compose.e2e.yml
export POSTGRES_PASSWORD=postgres
export KEYCLOAK_ADMIN_PASSWORD=admin
export OIDC_CLIENT_SECRET=change-me
export E2E_PASSWORD=test-password

docker compose up --build --wait
cd scenario-tests
uv sync
OIDC_CLIENT_SECRET=change-me E2E_PASSWORD=test-password uv run behave

Run mutation testing from Linux or WSL because mutmut requires fork support:

uv run --group test --with mutmut mutmut run

Maintenance

The GitHub Actions workflow runs Ruff, Ty, unit tests, integration tests, coverage, Docker image build validation, and scenario tests. Dependabot keeps dependency updates visible, while SonarCloud and Snyk expose code-quality and security status at the top of this README.

About

An opinionated FastAPI template with async SQLAlchemy 2.0, Alembic migrations, Pydantic v2, uv package manager, Docker, pytest, and pre-configured CI/CD. Python 3.13+ boilerplate for building REST APIs.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors