/library / template-fastapi-microservice
templateAPI / Backend

Python FastAPI microservice with SQLAlchemy + Pydantic v2

A small FastAPI service. Pydantic v2 schemas, SQLAlchemy 2.x async, Alembic migrations, structlog, pytest with httpx. Use when you want Python typing + speed without dragging in a framework.

use whenML inference endpoint, data ingestion service, or any backend where Python's ecosystem (numpy, pandas, etc) is the reason you're not using Node.

May 6, 20262,280 bytespythonfastapipydanticsqlalchemymicroservice

[Service Name]

A single-purpose FastAPI service. Async by default. Postgres for state. Dockerized.

Source of truth

Production runs as a container on Fly or Railway. The Dockerfile + locked requirements.txt define what runs. Local mirrors via docker compose up.

Tech stack

Python 3.13 + FastAPI 0.115 + Uvicorn. Pydantic v2 for request and response schemas. SQLAlchemy 2.x with the async API. Alembic for migrations. structlog for JSON logs. pytest + httpx for tests (real ASGI calls, no test client wrapping). uv for dependency management (way faster than pip).

Deploy

Build the Docker image, push to Fly or Railway. Health check at /healthz. Graceful shutdown via SIGTERM (FastAPI handles it).

File map

  • app/main.py FastAPI app + route mounting
  • app/api/ routers, one per resource
  • app/schemas/ Pydantic models (request, response)
  • app/models/ SQLAlchemy ORM models
  • app/db.py engine + session factory
  • app/deps.py reusable dependencies (auth, db session)
  • app/settings.py Pydantic Settings (env loading)
  • alembic/ migration history
  • tests/ pytest specs
  • Dockerfile slim Python image, multi-stage

.env keys

  • DATABASE_URL postgresql+asyncpg://...
  • API_KEY shared secret for inbound auth (if no JWT)
  • LOG_LEVEL
  • SENTRY_DSN optional

Hard rules

  • Every endpoint declares response_model. No untyped JSON dicts.
  • DB sessions via FastAPI Depends. Never instantiate AsyncSession in a handler.
  • Migrations via Alembic auto-generate + manual review. Never edit applied migrations.
  • Settings via Pydantic Settings class. No os.environ.get in business code.
  • pytest runs against a throwaway Postgres in CI. No mocks for the DB layer.
  • All structured logs include request_id set in middleware.

Recent significant changes

  • 2026-05-06: Scaffolded. Locked: Pydantic v2 (faster), SQLAlchemy 2.x async (not Tortoise), uv (not poetry).

Next session: start here

  1. uv venv && uv sync to install.
  2. Create Postgres locally with docker compose up db.
  3. alembic upgrade head to apply schema.
  4. uvicorn app.main:app --reload.
  5. Test /healthz, then implement the first business route.

Get the next CLAUDE.md in your inbox.

One new template every week, plus occasional case studies.