6.3 KiB
Alembic Database Migrations
This directory contains Alembic database migrations for the LOAF membership platform.
What is Alembic?
Alembic is a lightweight database migration tool for SQLAlchemy. It allows you to:
- Track database schema changes over time
- Apply migrations incrementally
- Roll back changes if needed
- Auto-generate migration scripts from model changes
Directory Structure
alembic/
├── versions/ # Migration scripts (KEEP IN VERSION CONTROL)
│ └── *.py # Individual migration files
├── env.py # Alembic environment configuration
├── script.py.mako # Template for new migration files
└── README.md # This file
Quick Start
1. Create a New Migration
After making changes to models.py, generate a migration:
cd backend
alembic revision --autogenerate -m "add_user_bio_field"
This will create a new file in alembic/versions/ like:
3e02c74581c9_add_user_bio_field.py
2. Review the Generated Migration
IMPORTANT: Always review auto-generated migrations before applying them!
# Open the latest migration file
cat alembic/versions/3e02c74581c9_add_user_bio_field.py
Check:
- ✅ The
upgrade()function contains the correct changes - ✅ The
downgrade()function properly reverses those changes - ✅ No unintended table drops or data loss
3. Apply the Migration
# Apply all pending migrations
alembic upgrade head
# Or apply migrations one at a time
alembic upgrade +1
4. Rollback a Migration
# Rollback the last migration
alembic downgrade -1
# Rollback to a specific revision
alembic downgrade 3e02c74581c9
Common Commands
| Command | Description |
|---|---|
alembic current |
Show current migration revision |
alembic history |
Show migration history |
alembic heads |
Show head revisions |
alembic upgrade head |
Apply all pending migrations |
alembic downgrade -1 |
Rollback last migration |
alembic revision --autogenerate -m "message" |
Create new migration |
alembic stamp head |
Mark database as up-to-date without running migrations |
Migration Workflow
For Development
-
Make changes to
models.py# In models.py class User(Base): # ...existing fields... bio = Column(Text, nullable=True) # New field -
Generate migration
alembic revision --autogenerate -m "add_user_bio_field" -
Review the generated file
# In alembic/versions/xxxxx_add_user_bio_field.py def upgrade(): op.add_column('users', sa.Column('bio', sa.Text(), nullable=True)) def downgrade(): op.drop_column('users', 'bio') -
Apply migration
alembic upgrade head -
Commit migration file to Git
git add alembic/versions/xxxxx_add_user_bio_field.py git commit -m "Add user bio field"
For Production Deployment
Fresh Database (New Installation):
# 1. Create database
createdb membership_db
# 2. Run initial schema SQL (creates all 17 tables)
psql -U username -d membership_db -f ../migrations/000_initial_schema.sql
# 3. Mark database as up-to-date with Alembic
alembic stamp head
# 4. Verify
alembic current # Should show: 001_initial_baseline (head)
Existing Database (Apply New Migrations):
# 1. Pull latest code
git pull origin main
# 2. Apply migrations
alembic upgrade head
# 3. Verify
alembic current
# 4. Restart application
systemctl restart membership-backend
Configuration
Database Connection
Alembic reads the DATABASE_URL from your .env file:
DATABASE_URL=postgresql://user:password@localhost:5432/membership_db
The connection is configured in alembic/env.py (lines 29-36).
Target Metadata
Alembic uses Base.metadata from models.py to detect changes:
# In alembic/env.py
from models import Base
target_metadata = Base.metadata
Important Notes
✅ DO:
- Always review auto-generated migrations before applying
- Test migrations in development before production
- Commit migration files to version control
- Write descriptive migration messages
- Include both
upgrade()anddowngrade()functions
❌ DON'T:
- Don't edit migration files after they've been applied in production
- Don't delete migration files from
alembic/versions/ - Don't modify the
revisionordown_revisionvalues - Don't commit
.pycfiles (already in .gitignore)
Migration History
| Revision | Description | Date | Type |
|---|---|---|---|
001_initial_baseline |
Baseline marker (empty migration) | 2026-01-02 | Baseline |
Note: The actual initial schema is created by running backend/migrations/000_initial_schema.sql. The baseline migration is an empty marker that indicates the starting point for Alembic tracking.
Troubleshooting
"Target database is not up to date"
# Check current revision
alembic current
# Check pending migrations
alembic history
# Apply missing migrations
alembic upgrade head
"FAILED: Can't locate revision identified by 'xxxxx'"
The database thinks it's at a revision that doesn't exist in your alembic/versions/.
Solution:
# Mark database at a known good revision
alembic stamp head
Migration conflicts
If you get merge conflicts in migration files:
- Resolve conflicts in the migration file
- Ensure
revisionanddown_revisionchain is correct - Test the migration locally
Fresh database setup
For a completely new database:
# Step 1: Run initial schema SQL
psql -U username -d membership_db -f ../migrations/000_initial_schema.sql
# Step 2: Mark as up-to-date
alembic stamp head
# Step 3: Verify
alembic current # Should show: 001_initial_baseline (head)
Legacy Migrations
Old numbered SQL migrations (000_initial_schema.sql through 011_wordpress_import_enhancements.sql) are preserved in backend/migrations/ for reference. These have been consolidated into the initial Alembic migration.
Going forward, all new migrations must use Alembic.