| name | database-migrator |
| description | Handle schema changes and data migrations safely. Creates migration files with rollback plans. Use when user says 'migration', 'schema change', 'add column', 'database change', or 'alter table'. |
| allowed-tools | Bash, Read, Write, Edit |
Database Migrator
You are an expert at handling database schema changes safely.
When To Use
- Adding/removing/modifying database columns
- Creating new tables
- Data transformations needed
- User says "Add this field", "Change the schema"
Inputs
- Current schema
- Desired change
- Data preservation requirements
Outputs
- Migration file(s)
- Rollback strategy
- Updated schema documentation
Workflow
1. Analyze Change
- Is this additive (safe) or destructive (risky)?
- Any data to preserve or transform?
- Downtime required?
2. Generate Migration
alembic revision --autogenerate -m "add user preferences"
npx prisma migrate dev --name add_preferences
3. Review Migration
- Check generated SQL
- Verify rollback works
- Consider indexes
4. Test Locally
alembic upgrade head
alembic downgrade -1
5. Document
- Update ERD if exists
- Note in LLM-OVERVIEW.md
Safe Migration Patterns
| Change | Safe? | Notes |
|---|
| Add nullable column | ✅ | No data change needed |
| Add column with default | ✅ | Backfills automatically |
| Remove unused column | ⚠️ | Verify no code references |
| Rename column | ❌ | Requires code coordination |
| Change column type | ❌ | May lose data |
| Add index | ✅ | May lock table briefly |
| Add foreign key | ⚠️ | Existing data must be valid |
Migration Templates
SQLite
ALTER TABLE users ADD COLUMN preferences TEXT;
PostgreSQL
ALTER TABLE users ADD COLUMN preferences JSONB DEFAULT '{}';
ALTER TABLE users DROP COLUMN preferences;
Alembic (Python)
"""add preferences column
Revision ID: abc123
"""
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('users',
sa.Column('preferences', sa.JSON(), nullable=True)
)
def downgrade():
op.drop_column('users', 'preferences')
Zero-Downtime Patterns
Adding Column
- Add column (nullable)
- Deploy code that writes to new column
- Backfill existing data
- Add NOT NULL constraint (if needed)
Renaming Column
- Add new column
- Deploy code that writes to both
- Backfill old → new
- Deploy code that reads from new
- Drop old column
Rollback Strategy
Always have a plan:
migration: add_preferences
rollback:
command: "alembic downgrade -1"
data_loss: false
downtime: "~30 seconds"
tested: true
NoSQL Migrations
MongoDB Schema Evolution
Unlike SQL, MongoDB is schema-less but you still need to manage document structure changes.
Adding a Field
db.users.updateMany(
{ preferences: { $exists: false } },
{ $set: { preferences: {} } }
);
Renaming a Field
db.users.updateMany(
{},
[{ $set: { newName: "$oldName" } }]
);
db.users.updateMany(
{},
{ $unset: { oldName: "" } }
);
Changing Field Type
db.users.updateMany(
{},
[{ $set: { age: { $toInt: "$age" } } }]
);
db.users.updateMany(
{},
[{
$set: {
city: "$address.city",
country: "$address.country"
},
$unset: "address"
}]
);
MongoDB Migration Script Template
module.exports = {
async up(db) {
await db.collection('users').updateMany(
{ preferences: { $exists: false } },
{ $set: { preferences: { theme: 'light', notifications: true } } }
);
},
async down(db) {
await db.collection('users').updateMany(
{},
{ $unset: { preferences: "" } }
);
}
};
Redis Data Evolution
Redis doesn't have migrations per se, but key naming and data structure changes need planning.
Key Naming Convention
# Good: namespace:entity:id:attribute
user:123:profile
user:123:sessions
cache:products:list
# Bad: no structure
user_profile_123
Changing Key Structure
import redis
r = redis.Redis()
for key in r.scan_iter("user_*"):
user_id = key.decode().split("_")[1]
new_key = f"user:{user_id}:profile"
r.copy(key, new_key)
for key in r.scan_iter("user_*"):
r.delete(key)
When SQL vs NoSQL
| Factor | Use SQL | Use NoSQL |
|---|
| Schema | Fixed, well-known | Flexible, evolving |
| Relationships | Many, complex | Few, embedded |
| Transactions | Critical | Nice to have |
| Scale | Vertical first | Horizontal first |
| Query patterns | Complex joins | Key-value, document |
| Data size | <100GB | Any size |
Default to SQL (SQLite → PostgreSQL) unless you have specific NoSQL needs.
Anti-Patterns
- Migrations without rollback plan
- Destructive changes without backup
- Long-running migrations during peak hours
- Not testing migrations locally first
- Combining multiple changes in one migration
- MongoDB: Not validating document structure
- Redis: Not using key namespaces
Keywords
migration, schema change, add column, database, alter table, alembic, prisma, mongodb, redis, nosql