SQL Migrations with Alembic
Migrations should be performed after each modification of the SQL schema. Since we use SQLAlchemy as our ORM, we leverage Alembic to handle database migrations seamlessly.
Migration Workflow
Section titled “Migration Workflow”Step 1: Generate a Migration Script
Section titled “Step 1: Generate a Migration Script”When generating migrations, always provide a clear, descriptive revision message. This helps maintain a readable migration history.
Example revision messages:
"create users table""add index to email column""rename column full_name to name""add foreign key from orders to users""remove deprecated table sessions""update default value for created_at"
Command:
docker compose up -d rdbdocker compose \ run --no-deps --build --rm \ --entrypoint "uv run alembic -c /app/openrag/scripts/migrations/alembic/alembic.ini revision --autogenerate -m '<revision_message>'" \ openragIt will create a new migration script in the openrag/scripts/migrations/alembic/versions/ directory.
Step 2: Apply the Migration
Section titled “Step 2: Apply the Migration”Once you’ve reviewed the generated migration script and confirmed it looks correct, apply it to your database:
docker compose up -d rdbdocker compose \ run --no-deps --build --rm \ --entrypoint "uv run alembic -c /app/openrag/scripts/migrations/alembic/alembic.ini upgrade head" \ openrag; docker compose downThis upgrades your database schema to the latest revision.
Troubleshooting: Multiple Alembic Heads
Section titled “Troubleshooting: Multiple Alembic Heads”If you encounter an error like:
ERROR [alembic.util.messaging] Multiple head revisions are present for given argument 'head'; please specify a specific target revision, '<branchname>@head' to narrow to a specific head, or 'heads' for all headsThis usually happens when two or more migration scripts are created independently from the same base revision (for example, when working on separate features that both modify the RDB schema). Alembic then detects multiple “heads” in the migration history.
How to resolve:
-
Create a merge migration to join the two heads. Replace the revision IDs below with your actual head revisions:
Merge Alembic heads docker compose up -d rdbdocker compose run --no-deps --build --rm \--entrypoint "uv run alembic -c /app/openrag/scripts/migrations/alembic/alembic.ini merge -m 'merge heads' <head1> <head2>" \openragThis will generate a new migration script that merges the two branches.
-
Apply the migrations as usual:
Apply migrations after merge docker compose up -d rdbdocker compose run --no-deps --build --rm \--entrypoint "uv run alembic -c /app/openrag/scripts/migrations/alembic/alembic.ini upgrade head" \openrag; docker compose down
Best Practices
Section titled “Best Practices”- Always review generated migration scripts before applying them
- Test migrations in a development environment first with the entire stack down
- Keep revision messages clear and concise
- Backup your database before running migrations in production
- Version control all migration scripts