Database Migrations Guide
This guide covers database migration management using Alembic for the Wegent Backend application.
Overviewβ
Alembic is a database migration tool for SQLAlchemy. It provides version control for your database schema, allowing you to track changes, apply upgrades, and rollback if needed.
Quick Startβ
View Current Migration Statusβ
# Check current database revision
alembic current
# View migration history
alembic history --verbose
Apply Migrationsβ
# Upgrade to the latest version
alembic upgrade head
# Upgrade by one version
alembic upgrade +1
# Upgrade to a specific revision
alembic upgrade <revision_id>
Rollback Migrationsβ
# Downgrade by one version
alembic downgrade -1
# Downgrade to a specific revision
alembic downgrade <revision_id>
# Downgrade to base (remove all migrations)
alembic downgrade base
Create New Migrationsβ
# Auto-generate a migration script based on model changes
alembic revision --autogenerate -m "description of changes"
# Create an empty migration script
alembic revision -m "description of changes"
After generating a migration script, always review it before applying to ensure it does what you expect.
Important Notesβ
Development vs Productionβ
- Development Mode: Migrations run automatically on application startup when
ENVIRONMENT=developmentandDB_AUTO_MIGRATE=True - Production Mode: Migrations must be run manually. The application will log a warning if there are pending migrations.
Best Practicesβ
- Always review auto-generated migrations - Alembic may not detect all changes correctly
- Test migrations on a copy of production data before applying to production
- Backup your database before running migrations in production
- Never edit applied migrations - create a new migration instead
- Keep migrations small and focused - easier to review and rollback if needed
Migration Safetyβ
- Initial migration uses
CREATE TABLE IF NOT EXISTSto safely handle existing databases - All migrations include both
upgrade()anddowngrade()functions for rollback support - Foreign key constraints are properly handled in the correct order
Common Commandsβ
# Navigate to backend directory first
cd /path/to/wegent/backend
# Check what migrations will be applied
alembic upgrade head --sql
# Show the diff between database and models
alembic upgrade head --sql > migration.sql
# Get help
alembic --help
alembic upgrade --help
Troubleshootingβ
Migration Failsβ
- Check database connection in
alembic.iniorDATABASE_URLenvironment variable - Review the migration script for errors
- Check database logs for detailed error messages
Conflict with Existing Tablesβ
If you have an existing database:
- The initial migration is designed to be safe with
CREATE TABLE IF NOT EXISTS - Run
alembic stamp headto mark the database as up-to-date without running migrations - Future migrations will then apply normally
Reset Migrationsβ
WARNING: This will drop all tables and data!
# Downgrade to base
alembic downgrade base
# Upgrade to latest
alembic upgrade head
Migration File Structureβ
backend/alembic/
βββ versions/ # Migration scripts (never edit after applying)
β βββ 0c086b93f8b9_initial_migration.py
β βββ b2c3d4e5f6a7_add_role_to_users.py # User role migration
βββ env.py # Alembic runtime environment
βββ script.py.mako # Template for new migrations
βββ README # Quick reference
Notable Migrationsβ
User Role Migration (b2c3d4e5f6a7)β
This migration adds the role column to the users table for role-based access control:
- Column:
role(VARCHAR(20), NOT NULL, default: 'user') - Values: 'admin' or 'user'
- Auto-upgrade: Users with
user_name='admin'are automatically set torole='admin'
The migration uses conditional SQL to safely handle cases where the column already exists.
Workflow Exampleβ
Here's a typical workflow for adding a new model field:
-
Modify the model in
backend/app/models/:# Add new field to model
class User(Base):
# ... existing fields ...
new_field = Column(String(100), nullable=True) -
Generate migration:
cd backend
alembic revision --autogenerate -m "add new_field to user table" -
Review the generated migration in
backend/alembic/versions/:- Check that the changes match your expectations
- Verify data type conversions
- Ensure nullable/default values are correct
-
Test the migration:
# Apply migration
alembic upgrade head
# Verify it works
# Test your application
# If needed, rollback
alembic downgrade -1 -
Commit the migration:
git add backend/alembic/versions/<new_migration>.py
git commit -m "feat(backend): add new_field to user table"