From grimoire
Guides writing versioned database migrations for schema changes (add/remove columns, tables, indexes, constraints) with rollback and testing practices.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:write-database-migrationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Version every schema change as a migration file committed alongside the code that requires it.
Version every schema change as a migration file committed alongside the code that requires it.
Adopted by: Every major web framework ships a migration tool: Rails ActiveRecord Migrations, Django Migrations, Laravel Migrations. Flyway is used at Google, Zalando, Wix; Liquibase is used at 10,000+ enterprises. Schema-as-code is the universal default in 2024 — ad-hoc ALTER scripts are considered a smell in professional engineering teams. Impact: Teams using versioned migrations report near-zero schema drift incidents between environments (dev/staging/prod). Automated rollback capability reduces mean time to recovery from hours (restore from backup) to minutes (down migration). Every change is code-reviewed, auditable via git log, and exactly reproducible across all environments. Why best: Ad-hoc ALTER scripts run manually have no audit trail, can't be replayed, diverge between environments, and can't be rolled back predictably. A migration file is committed in the same PR as the application code that requires it — impossible to deploy code that references a column that doesn't exist.
Sources: Fowler & Sadalage, "Evolutionary Database Design" (martinfowler.com/articles/evodb.html); Rails Active Record Migrations guide; Flyway documentation (flyway.org)
Never bundle unrelated alterations. Each migration should be independently deployable and independently rollbackable:
# Bad — one migration does too much
20240601_setup_users_and_orders.sql
# Good — separate concerns
20240601120000_create_users_table.sql
20240601120001_create_orders_table.sql
20240602090000_add_email_index_to_users.sql
Format: YYYYMMDDHHMMSS_<what_changed>.sql (or the equivalent in your framework).
The timestamp ensures deterministic ordering across branches and parallel development:
20240601120000_add_email_to_users.sql
20240601120001_create_sessions_table.sql
20240602090000_add_index_on_users_email.sql
Every migration must have a reversal path:
-- up
ALTER TABLE users ADD COLUMN email VARCHAR(255);
-- down
ALTER TABLE users DROP COLUMN email;
If the rollback is destructive (data loss), document it explicitly rather than omitting it:
-- down (WARNING: drops all email data — backup required before rollback)
ALTER TABLE users DROP COLUMN email;
Run the migration against a recent anonymized copy of the production database. Check:
Standard ALTER TABLE locks the table. On large tables, use non-locking patterns:
Adding a NOT NULL column with a default:
-- Step 1: Add nullable (no lock)
ALTER TABLE orders ADD COLUMN status VARCHAR(50);
-- Step 2: Backfill in batches (separate migration or script)
UPDATE orders SET status = 'pending' WHERE status IS NULL AND id BETWEEN 1 AND 10000;
-- ... repeat in batches
-- Step 3: Add NOT NULL constraint after backfill (fast — no data scan needed if all filled)
ALTER TABLE orders ALTER COLUMN status SET NOT NULL;
Adding an index: Use CREATE INDEX CONCURRENTLY (PostgreSQL) or equivalent.
Never create indexes without CONCURRENTLY on live tables with significant traffic.
A merged migration has run in staging or production. Editing it creates a divergence between the recorded migration history and the actual database state.
For corrections: add a new migration that fixes the error.
# Bad — editing merged migration
git commit -m "fix typo in 20240601_add_email_to_users" # already ran in prod
# Good — new corrective migration
20240603_rename_email_typo_to_correct_column.sql
CREATE TABLE IF NOT EXISTS, ADD COLUMN IF NOT EXISTS (PostgreSQL 9.6+)Skipping the down migration. The first time you need to roll back at 2am, an absent down migration forces a manual database restore.
Bundling schema changes with data migrations. Schema changes (DDL) and data transformations (DML) have different risk profiles and should be separate migrations.
Locking production tables. A plain ALTER TABLE on a 50M-row table can lock writes
for minutes. Always check whether your database's ALTER operation is non-locking.
Deploying code before its migration. Application code referencing users.email
will crash if the migration hasn't run. Always run migrations before deploying the
application code that requires them.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireCreates, validates, executes, and rolls back schema migrations for PostgreSQL, MySQL, MongoDB using Flyway, Alembic, Prisma, Knex.
Build zero-downtime database migrations — forward SQL, rollback SQL, deployment sequence. Use when asked to "write migration", "schema change", "add column", "rename table", "drop column", or "migrate safely".
Generates zero-downtime database migrations with forward SQL, rollback SQL, and deployment sequences for schema changes like adding columns, renaming tables, or dropping columns.