Alembic migrations
Schema evolution lives here going forward. The legacy hand-rolled
_migrate() function in backend/core/db.py is kept for the next release
as a fallback, and can be retired once Alembic has run in production.
Workflow
From the repo root:
# Create a new migration
uv run alembic revision -m "add glossary table"
# Apply pending migrations
uv run alembic upgrade head
# Show current schema version
uv run alembic current
# Downgrade one step
uv run alembic downgrade -1
Conventions
- SQLite-safe:
env.pysetsrender_as_batch=True, soALTER TABLEemits a table-rewrite strategy that works on SQLite. - No autogeneration: this repo has no SQLAlchemy models; every migration is
written by hand using
op.execute(...)or typed helpers likeop.add_column,op.create_table, etc. - No destructive migrations without review: if a migration deletes a column or drops a table, the PR must be explicit about it.
Bootstrap note
On first run against an existing DB already at legacy PRAGMA user_version = 2,
stamp Alembic to a baseline before applying new migrations:
uv run alembic stamp head
This tells Alembic that the schema is up-to-date as of the baseline version.