Alembic (Schema-Migrationen)
Alembic ist der Schema-Versionsmanager für PostGIS: DDL-Änderungen liegen als nummerierte Python-Revisionen im Repo. Die Datenbank speichert den aktuellen Stand; upgrade head wendet alle fehlenden Revisionen an. Schema von Null und nach Deploy: Alembic — kein Dump-Restore als Normalweg.
Denkmodell: wie Git für die Tabellenstruktur — Revisionen = Commits, head = Zielstand, Upgrade = Anwenden.
Entscheidung und Trennung Control/Mandant: ADR-0031. Ops: Setup, Deployment.
Zwei Revisionsketten
Ein gemeinsamer Alembic-Head würde Control-Tabellen (z. B. app_users) in Mandanten-DBs anlegen und umgekehrt. Deshalb zwei Ketten:
| Control-Plane | Mandant (Tenant) | |
|---|---|---|
| Datenbank | linetra (POSTGRES_DB) |
linetra_<slug> (eine pro aktivem tenants-Eintrag) |
| Inhalt | Login, tenants, app_users, Sessions, Rechte-Katalog, … |
Fachdaten (Projekte, Personen, Geo, Schema-Felder, …) |
| Revisionen | backend/alembic/versions/ |
backend/alembic/tenant/versions/ |
| Config | backend/alembic.ini |
backend/alembic.tenant.ini |
| Versions-Tabelle | alembic_version |
alembic_version_tenant |
Neue Mandanten: DB von Template oder Kopie, dann Tenant-Stamp; danach laufen sie mit den anderen über dasselbe Upgrade-Skript.
Befehle
Alles im Backend-Container, cwd Projektroot auf dem Host. Production-Images: uv run --no-dev (ohne Dev-Extras). Development-Image: uv run reicht.
Nur Control (selten allein nötig; das All-Skript deckt Control mit ab):
# Development
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile dev \
exec backend uv run alembic upgrade head
# Production
docker compose exec backend uv run --no-dev alembic upgrade head
Control + alle aktiven Mandanten (Deploy- und Day-2-Standard):
./scripts/alembic_upgrade_all.sh
Das Skript führt zuerst Control-upgrade head aus, dann für jede aktive Mandanten-DB alembic -c alembic.tenant.ini … upgrade head. Shared-Control-DB wird übersprungen.
DDL läuft als POSTGRES_USER (linetra_edit hat nur DML). Nach Image-/Code-Deploy mit Schema-Änderung immer das All-Skript — sonst bleiben Mandanten hinter dem Code.
Revisionen schreiben
Neue Schema-Änderung = neue Revisionsdatei (Review wie Code), upgrade() / möglichst downgrade(). Fach-DDL nur unter alembic/tenant/; Control-Plane nur unter alembic/versions/. Pin und Stack: ADR-0012, Backend-Standards in den Cursor-Regeln.