Skip to content

FastAPI Todo API

A REST API for managing todos, built with FastAPI and PostgreSQL. This example demonstrates async Python with database integration -- the same database: enabled: true pattern as Django, but with SQLAlchemy and Alembic instead of Django ORM and manage.py migrate.

Source: git@gitlab.com:appmecca-sample-apps/fastapi-todos.git

What This App Demonstrates

  • FastAPI (async Python) on AppMecca
  • Database integration with SQLAlchemy and Alembic migrations
  • Health check endpoint at /health (no trailing slash)
  • REST API patterns -- CRUD operations on a PostgreSQL-backed resource

appmecca.yaml

containers:
  - name: api
    dockerfile: Dockerfile
    context: .

deploy:
  - name: api
    container: api
    port: 8000
    health_check:
      path: /health

database:
  enabled: true

This is nearly identical to the Django Notes example. The only differences are the service name (api instead of web) and the health check path (no trailing slash).

Application Code

Database connection

FastAPI apps typically use SQLAlchemy with DATABASE_URL:

import os
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

DATABASE_URL = os.environ.get("DATABASE_URL", "postgresql://localhost/todos")

engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(bind=engine)

Health check

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
async def health():
    return {"status": "healthy"}

Entrypoint script

FastAPI apps use Alembic for migrations instead of Django's manage.py migrate:

#!/bin/bash
set -e

echo "==> Waiting for database..."

RETRIES=10
DELAY=3

for i in $(seq 1 $RETRIES); do
    python -c "
import psycopg2, os
try:
    conn = psycopg2.connect(os.environ.get('DATABASE_URL'))
    conn.close()
    print('Database is ready.')
except Exception as e:
    print(f'Database not ready: {e}')
    exit(1)
" && break
    echo "    Attempt $i/$RETRIES failed. Retrying in ${DELAY}s..."
    sleep $DELAY
done

echo "==> Running migrations..."
alembic upgrade head

echo "==> Starting uvicorn..."
exec uvicorn main:app --host 0.0.0.0 --port 8000

Use DATABASE_URL for connection checks

FastAPI apps can use the DATABASE_URL variable directly for the psycopg2 connection check. This is simpler than passing individual DB_HOST, DB_PORT, etc. variables. Both are injected by AppMecca.

Dockerfile

FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

WORKDIR /app

RUN apt-get update && \
    apt-get install -y --no-install-recommends libpq-dev && \
    rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

RUN chmod +x entrypoint.sh

EXPOSE 8000

ENTRYPOINT ["./entrypoint.sh"]

Deploy It

# Register the app
mecca register git@gitlab.com:appmecca-sample-apps/fastapi-todos.git -e dev

# Build the Docker image
mecca build trigger -e dev -g git@gitlab.com:appmecca-sample-apps/fastapi-todos.git

# Deploy
mecca app deploy -e dev fastapi-todos

Your API is live at https://fastapi-todos-api.dev.appmecca.net. The service name (api) is always part of the hostname — run mecca app show fastapi-todos -e dev for the exact URL, which also carries your group slug.

Verify

# Health check
curl https://fastapi-todos-api.dev.appmecca.net/health

# Create a todo
curl -X POST https://fastapi-todos-api.dev.appmecca.net/todos \
  -H "Content-Type: application/json" \
  -d '{"title": "Deploy more apps", "done": false}'

# List todos
curl https://fastapi-todos-api.dev.appmecca.net/todos

Django vs. FastAPI on AppMecca

Both frameworks use the exact same AppMecca configuration pattern. The differences are in your application code:

Django FastAPI
Migration tool python manage.py migrate alembic upgrade head
Server gunicorn + WSGI uvicorn + ASGI
Health check path /health/ (trailing slash) /health
Database config DATABASES dict in settings.py create_engine(DATABASE_URL)
AppMecca config Identical Identical

The appmecca.yaml doesn't care which framework you use. It just needs a port, a health check path, and database: enabled: true.

Key Takeaways

  • FastAPI works the same as Django on AppMecca -- just different migration and server commands
  • Use DATABASE_URL for the simplest connection setup with SQLAlchemy
  • The entrypoint script pattern (wait, migrate, start) is universal across frameworks
  • Use exec before the final command so Docker signals reach your application

What's Next?