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_URLfor the simplest connection setup with SQLAlchemy - The entrypoint script pattern (wait, migrate, start) is universal across frameworks
- Use
execbefore the final command so Docker signals reach your application
What's Next?¶
- Django + Vue Notes -- Same pattern with Django and Vue.js
- Flask + Redis Counter -- Add Redis caching to a Flask app
- Database Configuration -- Full reference for database settings