| name | database-migration |
| description | Database migrations with Alembic, rollbacks, and zero-downtime deployment. Use for schema changes. |
| globs | ["**/alembic/**","**/migrations/**"] |
| alwaysApply | false |
Database Migration Skill
Migration Lifecycle
1. Generate Migration
alembic revision --autogenerate -m "Add user preferences"
2. Review Generated Script
def upgrade():
op.create_table('user_preferences',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('theme', sa.String(), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['user.id']),
sa.PrimaryKeyConstraint('id')
)
def downgrade():
op.drop_table('user_preferences')
3. Add Indexes
def upgrade():
op.create_table(...)
op.create_index(
'ix_user_preferences_user_id',
'user_preferences',
['user_id']
)
def downgrade():
op.drop_index('ix_user_preferences_user_id')
op.drop_table('user_preferences')
4. Test Locally
alembic upgrade head
SELECT * FROM user_preferences;
alembic downgrade -1
SELECT COUNT(*) FROM user_preferences;
5. Test on Production-like Data
pg_dump production > backup.sql
psql staging < backup.sql
alembic upgrade head
EXPLAIN ANALYZE SELECT * FROM user_preferences WHERE user_id = 123;
6. Deploy with Zero Downtime
Backward Compatibility Rules
- ✅ Add columns with defaults
- ✅ Add tables
- ✅ Add indexes
- ✅ Change column types (with care)
- ❌ Drop columns without deprecation
- ❌ Rename columns without alias
- ❌ Change constraints abruptly
Versioning
- Never edit old migrations
- Always create new migration
- Migrations are immutable
- Name clearly:
001_initial_schema.py
Rollback Procedure
ALWAYS test downgrade first:
alembic current
alembic downgrade -1
alembic upgrade +2