Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generate database migration scripts for Liquibase, Flyway, Alembic with rollback safety, data preservation, and zero-downtime patterns
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 215% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 171% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 153% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 109% | 0% |
Trigger conditions:
Not for:
Time normalization:
NOW_ET using NIST/time.gov semantics (America/New_York, ISO-8601)NOW_ET for all citation access datesInput validation:
migration_tool must be one of: liquibase, flyway, alembicdatabase must be one of: postgresql, mysql, sqlserver, oraclemigration_type must be one of: schema, data, hybriddowntime_allowed must be boolean (true/false)migration_description must be non-empty and descriptiveSource freshness:
Fast path for simple DDL changes:
Liquibase (XML/YAML) accessed 2025-10-26T03:51:54-04:00 xml <changeSet id="add-email-column" author="migration-generator"> <addColumn tableName="users"> <column name="email" type="VARCHAR(255)"/> </addColumn> <rollback> <dropColumn tableName="users" columnName="email"/> </rollback> </changeSet>
Flyway (SQL) accessed 2025-10-26T03:51:54-04:00 sql -- V1__add_email_column.sql ALTER TABLE users ADD COLUMN email VARCHAR(255);
Alembic (Python) accessed 2025-10-26T03:51:54-04:00 python def upgrade(): op.add_column('users', sa.Column('email', sa.String(255)))
def downgrade(): op.drop_column('users', 'email')
Decision: If simple schema change without data → STOP at T1; otherwise proceed to T2.
Extended migrations with data transformations:
Backfill Existing Data python # Alembic: Backfill default values for new column def upgrade(): op.add_column('users', sa.Column('status', sa.String(20), nullable=True)) # Backfill existing rows op.execute("UPDATE users SET status = 'active' WHERE status IS NULL") # Make NOT NULL after backfill op.alter_column('users', 'status', nullable=False)
Data Transformation python # Alembic: Split full_name into first_name and last_name def upgrade(): op.add_column('users', sa.Column('first_name', sa.String(100))) op.add_column('users', sa.Column('last_name', sa.String(100))) # Transform data connection = op.get_bind() users = connection.execute("SELECT id, full_name FROM users").fetchall() for user_id, full_name in users: parts = full_name.split(' ', 1) first = parts[0] last = parts[1] if len(parts) > 1 else '' connection.execute( "UPDATE users SET first_name = %s, last_name = %s WHERE id = %s", (first, last, user_id) ) op.drop_column('users', 'full_name')
sql -- Post-migration validation SELECT COUNT(*) FROM users WHERE email IS NULL; -- Should be 0 SELECT COUNT(*) FROM users WHERE status NOT IN ('active', 'inactive'); -- Should be 0
PostgreSQL accessed 2025-10-26T03:51:54-04:00
ALTER TABLE ... SET NOT NULL with CHECK constraint firstCONCURRENTLY for index creation (zero-downtime)pg_stat_progress_create_index to monitor long operationsMySQL accessed 2025-10-26T03:51:54-04:00
ALGORITHM=INPLACE, LOCK=NONEALTER TABLE that requires table copy (pre-8.0)pt-online-schema-change for large tables (Percona Toolkit)SQL Server
WITH (ONLINE = ON) for index operationsSSMS execution plan analysisSCHEMA_ONLY copies for large data migrationsAdvanced patterns for production systems:
Phase 1: Expand (Add new schema) python # Migration 001: Add new column, keep old column def upgrade(): op.add_column('users', sa.Column('email_new', sa.String(255))) # Trigger to sync old → new during transition op.execute(""" CREATE TRIGGER sync_email_new BEFORE UPDATE ON users FOR EACH ROW BEGIN SET NEW.email_new = NEW.email; END; """)
Phase 2: Migrate Data python # Migration 002: Backfill new column def upgrade(): op.execute("UPDATE users SET email_new = email WHERE email_new IS NULL")
Phase 3: Contract (Remove old schema) python # Migration 003: Drop old column (after application updated) def upgrade(): op.execute("DROP TRIGGER IF EXISTS sync_email_new") op.drop_column('users', 'email') op.alter_column('users', 'email_new', new_column_name='email')
PostgreSQL CONCURRENTLY sql -- Flyway: V5__add_email_index.sql CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
-- Validation SELECT schemaname, tablename, indexname, indexdef FROM pg_indexes WHERE indexname = 'idx_users_email';
MySQL Online DDL sql -- Flyway: V6__add_composite_index.sql ALTER TABLE users ADD INDEX idx_email_status (email, status) ALGORITHM=INPLACE, LOCK=NONE;
python # Migration 010: Create shadow table with new schema def upgrade(): op.create_table( 'users_new', sa.Column('id', sa.Integer, primary_key=True), sa.Column('email', sa.String(255), nullable=False, index=True), sa.Column('status', sa.String(20), nullable=False) ) # Stream data from old → new table op.execute(""" INSERT INTO users_new (id, email, status) SELECT id, email, COALESCE(status, 'active') FROM users """) # Atomic rename (downtime: milliseconds) op.rename_table('users', 'users_old') op.rename_table('users_new', 'users')
markdown ## Deployment Steps
### Pre-Migration
### Migration Execution
SELECT * FROM pg_locks WHERE NOT grantedSELECT COUNT(*) FROM users### Post-Migration
### Rollback Procedure (if needed)
flyway undo or alembic downgrade -1SELECT * FROM users LIMIT 10Migration Tool Selection:
Migration Strategy by Downtime Allowance:
Database-Specific Patterns:
Abort Conditions:
Data Preservation Checks:
Schema (JSON):
json{ "migration_tool": "liquibase | flyway | alembic", "database": "postgresql | mysql | sqlserver | oracle", "migration_type": "schema | data | hybrid", "downtime_allowed": "boolean", "migration_script": { "filename": "string (e.g., V5__add_email_column.sql)", "content": "string (tool-specific migration code)" }, "rollback_script": { "filename": "string (e.g., U5__undo_email_column.sql)", "content": "string (inverse migration code)", "manual_steps": ["string (if auto-rollback unsafe)"] }, "validation_tests": [ { "description": "string", "query": "string (SQL validation query)", "expected_result": "string" } ], "deployment_guide": { "pre_migration_steps": ["string"], "execution_steps": ["string"], "post_migration_steps": ["string"], "rollback_procedure": ["string"], "estimated_duration": "string (e.g., '5 minutes', '2 hours')" }, "warnings": ["string (potential issues or breaking changes)"], "timestamp": "ISO-8601 string (NOW_ET)" }
Required Fields:
migration_tool, database, migration_type, downtime_allowed, migration_script, rollback_script, validation_tests, deployment_guide, timestampSafety Guarantees:
Example 1: Simple Column Addition (Alembic + PostgreSQL)
python"""Add email column to users table with NOT NULL constraint Revision ID: a1b2c3d4e5f6 Revises: previous_revision Create Date: 2025-10-26 03:51:54.000000 """ from alembic import op import sqlalchemy as sa def upgrade(): # Add column as nullable first op.add_column('users', sa.Column('email', sa.String(255), nullable=True)) # Backfill with placeholder (application will update) op.execute("UPDATE users SET email = CONCAT('user', id, '@example.com') WHERE email IS NULL") # Add NOT NULL constraint op.alter_column('users', 'email', nullable=False) # Add index for performance op.create_index('idx_users_email', 'users', ['email'], unique=True) def downgrade(): op.drop_index('idx_users_email', table_name='users') op.drop_column('users', 'email')
Token Budgets:
Safety:
Auditability:
Determinism:
Performance:
Official Documentation (accessed 2025-10-26T03:51:54-04:00):
Migration Patterns:
Best Practices:
Tool Comparisons:
Other measured skills in the registry, with their headline benchmark lift.