Skip to content

Repository files navigation

⚡ FastAPI API Template

This template provides a robust starting point for building APIs with FastAPI. It includes user authentication, CRUD operations, JWT token-based authentication, and PostgreSQL integration. The setup is streamlined with Docker and includes comprehensive documentation and testing tools.

📌 Features

  • 🔐 User authentication with basic login and Google Auth
  • 👥 User management with creation and CRUD operations
  • 📄 Example endpoints for Posts, Users, and Votes
  • 💓 API healthcheck endpoint
  • 🔑 JWT token-based authentication
  • ⚙️ Middleware support
  • 🌎 CORS configuration
  • 📝 Comprehensive Swagger API documentation
  • 🐘 PostgreSQL database integration
  • 🔒 Field encryption for sensitive data

💾 Installation

Important

Min Python version: 3.14

Clone this repo:

git clone https://github.com/ezeparziale/fastapi-api-template

Create virtual environment:

python -m venv env

Activate environment:

  • Windows:
. env/scripts/activate
  • Mac/Linux:
. env/bin/activate

Upgrade pip:

python -m pip install --upgrade pip

Install requirements:

pip install -r requirements-dev.txt

Install pre-commit:

pre-commit install

🔧 Config

Create .env file. Check the example .env.example

🌐 Google Auth credentials:

Create your app and obtain your client_id and secret:

https://developers.google.com/workspace/guides/create-credentials

🔒 How to create a secret key:

openssl rand -base64 64

🔐 How to create an encryption key:

To create an encryption key for securing sensitive data, you can use the generate_key.py script provided in the repository. Run the following command:

python generate_key.py

This will generate a secure encryption key.

🚧 Before first run:

Run docker-compose 🐳 to start the database server

docker compose -f "compose.yaml" up -d --build adminer db

and init the database with alembic:

alembic upgrade head

🔑 Create a self-signed certificate with openssl:

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365

🏃 Run

uvicorn app.main:app --reload --port 8000 --env-file .env --ssl-keyfile key.pem --ssl-certfile cert.pem

--env-file .env is what puts OTEL_* in the environment, the monitoring stack needs it.

🚨 Lint

Run linter and formatter

scripts/lint.sh
scripts/format.sh

🧑‍💻 Coverage

Run coverage

coverage run -m pytest
coverage report --show-missing
coverage html

Or run all in one with:

scripts/coverage.sh

🧪 Test

Run pytest with coverage

coverage run -m pytest

or

scripts/test.sh

🛠️ Alembic

Alembic is used for database migrations. Below are some common commands to manage your database schema.

Autogenerate a revision

To autogenerate a new revision based on the changes detected in your models, run:

alembic revision --autogenerate -m "your message here"

Generate a blank revision

To create a blank revision for custom migrations, run:

alembic revision -m "your message here"

Upgrade the database

To apply the latest migrations and upgrade the database schema, run:

alembic upgrade head

Downgrade the database

To revert the last migration and downgrade the database schema, run:

alembic downgrade -1

After creating a revision, you can edit the generated script to define your custom migrations.

📊 Monitoring

Traces, metrics and logs with Grafana, Tempo, Prometheus, Loki and Alloy.

FastAPI has OpenTelemetry built in, so the app only needs OTEL_EXPORTER_OTLP_ENDPOINT in .env. It sends OTLP to Alloy, and Alloy routes each signal to its store:

app ──OTLP────> alloy ──traces──> tempo ──remote_write (span + service graph metrics)──> prometheus
   stdout ──> alloy ──metrics─> prometheus
             └──logs───> loki
grafana reads tempo + prometheus + loki

🚀 Setup

  1. Start the stack:

    docker compose up -d alloy tempo prometheus loki grafana
  2. Open Grafana on http://localhost:3000 with admin / admin. The data sources and the dashboards are provisioned automatically.

  3. Send some traffic so there is something to look at:

    curl http://localhost:8000/health
  4. Explore the provisioned dashboards:

    • Overview / Golden Signals: traffic, errors, latency and saturation, the entry point
    • App Logs: log lines plus the share of logs per level
    • Request Metrics: throughput, latency percentiles and error rate
    • APM / Service Overview: service graph, span RED metrics and recent traces

    Or query the data sources by hand from Grafana > Explore: Tempo for traces, Prometheus for metrics, Loki for logs.

📊 Useful endpoints:

Service URL
Grafana http://localhost:3000
Alloy UI http://localhost:12345
Prometheus http://localhost:9090
Tempo http://localhost:3200
Loki http://localhost:3100

🔎 How the dashboards work:

The app writes one JSON object per line (loguru with serialize=True), so the level is nested at record.level.name and the message at record.message. The logs panel queries use | json, and Loki exposes those nested fields flattened with underscores, which is where record_level_name comes from.

Request Metrics is built on http.server.request.duration, the histogram FastAPI records for every request. Percentiles come from histogram_quantile() over the buckets, and error rate is the share of 5xx responses. Two details worth knowing:

  • Paths that match no route, such as a 404, carry no http_route label, so they are grouped as unmatched with label_replace().
  • Both error rate panels read 0% while healthy instead of showing no data, so a quiet dashboard never looks broken.

Overview / Golden Signals is the single pane over the four signals. Traffic, errors and latency come from http.server.request.duration and saturation from http.server.active_requests, the in-flight request gauge FastAPI exports. The bottom row repeats the golden signals from the trace side (traces_spanmetrics_*) so both pipelines are visible side by side, and the dashboard header links through to Request Metrics and APM / Service Overview for the drill-down.

APM / Service Overview is built on the metrics the Tempo metrics-generator derives from the traces, not on the app's own HTTP histogram. The generator is enabled in tempo/tempo.yaml (the metrics_generator block plus the overrides.defaults.metrics_generator.processors list) and remote-writes two families of series back into Prometheus:

  • traces_spanmetrics_* — RED metrics per span (calls_total, latency_bucket, size_total), labeled by service, span_name, span_kind and status_code.
  • traces_service_graph_* — per-edge request counts, failures and durations between a client and a server, which draw the node graph.

Two things are worth knowing:

  • The Service Graph panel is a Tempo query (queryType: serviceMap), not a PromQL panel. It resolves the traces_service_graph_* series through the Prometheus data source linked under serviceMap in the Tempo data source.
  • Prometheus needs --web.enable-remote-write-receiver for the generator to push into it; without that flag the generator logs remote-write failures and the dashboard stays empty.

⚠️ The OTLP receiver in Prometheus scrapes every 60s and ignores global.scrape_interval, so the Prometheus data source declares timeInterval: 60s. That matters because $__rate_interval is derived from it: at the 15s default it lands near 1m, which is too short to hold two samples, and every rate() in the dashboards returns nothing. Leave it in sync if you ever change the receiver cadence.

⚠️ Alloy reads the host Docker socket to collect container logs. It grants root equivalent access to the host, fine for local work, and must be replaced by a scoped socket proxy anywhere shared.

🛠️ Configuration files:

observability/
├── docker/
│   ├── alloy/config.alloy                # OTLP and Docker logs in, traces, metrics and logs out
│   ├── prometheus/prometheus.yml
│   ├── tempo/tempo.yaml                  # storage + metrics-generator (span metrics, service graph)
│   └── loki/loki-config.yaml
└── grafana/
    ├── dashboards/
    │   ├── golden-signals-overview.json  # traffic, errors, latency, saturation
    │   ├── app-logs.json                 # log lines and share per level
    │   ├── request-metrics.json          # throughput, latency percentiles, error rate
    │   └── apm-service-overview.json     # service graph, span RED metrics, traces
    └── provisioning/
        ├── dashboards/dashboards.yaml
        └── datasources/datasources.yaml

Releases

Packages

Used by

Contributors

Languages