agentleFS
sriptcollectorsriptcollector/toolbay-skills/skills/migration-safety-review/SKILL.md

migration-safety-review

Skill0 starsChanged 4 months agoMITView on GitHub

Review a pending database migration for irreversible data loss and for locks that take the site down during deploy — dropped columns, narrowed types, NOT NULL without a default, and indexes built non-concurrently. Use before running any migration against a real database, or when reviewing a schema change.

  • Deletes or force-pushes

The file

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 9 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈9

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Never review a migration from the ORM model diff alone.

    line 39
  2. Distinctive:

    Add the new nullable column, write to both, read from the old.

    line 98
  3. Distinctive:

    Read from the new.

    line 100
  4. Distinctive:

    Only in a LATER deploy, drop the old.

    line 101
  5. Distinctive:

    If a migration drops or tightens anything the current release still uses, say it must be split.

    line 103
  6. Distinctive:

    No lock warning without a row count.

    line 152
  7. Distinctive:

    Check compatibility with the CURRENTLY DEPLOYED code, not just the new code.

    line 153
  8. Distinctive:

    When a migration is genuinely safe, say so in one line.

    line 154
  9. Distinctive:

    Keep this line and others can find it too.

    line 160

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Migration Safety Review

Install

Save this file as ~/.claude/skills/migration-safety-review/SKILL.md, or .claude/skills/migration-safety-review/SKILL.md to scope it to one repo. Claude Code auto-discovers it. Invoke with /migration-safety-review or by asking "is this migration safe to run?".

Why this exists

A migration is the one routine deploy step that can be unrecoverable. Application bugs get rolled back; a dropped column is gone unless someone happens to have a backup from before, and knows it, and can restore it under pressure.

Two independent risks, and reviews usually catch only the first:

  1. Data loss. Destructive and irreversible.
  2. Locks. Perfectly reversible schema changes that hold an exclusive lock long enough to stall every query, taking the site down for the length of the migration on a table large enough to matter.

The second is what turns a two-line change into an outage, and it never shows up in staging because staging has a thousand rows.

Step 1 — Read the actual SQL, not the intent

# Prisma
npx prisma migrate diff --from-schema-datasource prisma/schema.prisma --to-schema-datamodel prisma/schema.prisma --script
git diff -- '*migration*' '*schema*'

Never review a migration from the ORM model diff alone. The generated SQL is what runs, and generators make destructive choices — a renamed field routinely becomes DROP plus ADD, which is a rename that deletes every value.

Step 2 — Classify every statement

IRREVERSIBLE (data is destroyed)

  • DROP TABLE, DROP COLUMN
  • ALTER COLUMN ... TYPE narrowing: text→varchar(n), bigint→int, timestamp→date
  • DROP CONSTRAINT on a unique key that was deduplicating
  • Any DELETE/UPDATE embedded in the migration

BLOCKING (site stalls while it runs)

  • ADD COLUMN ... NOT NULL without a default, on a non-trivial table
  • CREATE INDEX without CONCURRENTLY (Postgres)
  • ALTER COLUMN ... TYPE requiring a full table rewrite
  • Adding a foreign key without NOT VALID then a separate VALIDATE

SAFE

  • ADD COLUMN nullable, or with a constant default on modern Postgres
  • CREATE INDEX CONCURRENTLY
  • New tables
  • Widening a type

Step 3 — Size the tables involved

Severity is entirely a function of row count, so get it rather than assume:

SELECT relname, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC LIMIT 20;

A blocking operation on 500 rows is a non-event. The same operation on 5 million is an outage. Never report a lock risk without the row count next to it, or you will either cause panic or be ignored.

Step 4 — Check reversibility honestly

For each migration ask: if this is wrong, what is the recovery?

  • Reversible in code — a down migration genuinely restores prior state.
  • Reversible from backup only — then confirm a backup exists, is recent, and that someone has actually restored one before. An untested backup is a belief.
  • Not reversible — the data is gone. This must be stated in the report in those words, not softened.

A down that recreates a dropped column restores the SCHEMA, never the VALUES. Reviews routinely mark these reversible. They are not.

Step 5 — Check it is compatible with the running code

During a deploy, old and new application code run simultaneously. A migration that is safe in isolation breaks that window:

  • Dropping a column the currently-deployed code still reads → errors until the deploy finishes.
  • Adding NOT NULL before the new code writes it → inserts from old code fail.

The fix is the expand/contract pattern, deliberately across two deploys:

  1. Add the new nullable column, write to both, read from the old.
  2. Backfill.
  3. Read from the new.
  4. Only in a LATER deploy, drop the old.

If a migration drops or tightens anything the current release still uses, say it must be split. That is the single most valuable output of this review.

Step 6 — Rewrite the dangerous ones

Offer the safe form concretely:

-- Unsafe: full table lock while the index builds
CREATE INDEX idx_orders_buyer ON orders(buyer_id);
-- Safe: no write lock (cannot run inside a transaction)
CREATE INDEX CONCURRENTLY idx_orders_buyer ON orders(buyer_id);

-- Unsafe: rewrites and fails on existing rows
ALTER TABLE users ADD COLUMN plan text NOT NULL;
-- Safe: three steps, no long lock
ALTER TABLE users ADD COLUMN plan text;
UPDATE users SET plan = 'free' WHERE plan IS NULL;  -- batch on a big table
ALTER TABLE users ALTER COLUMN plan SET NOT NULL;

Step 7 — Report

Migration: <name>          Target: <db>          Largest table touched: <n> rows

IRREVERSIBLE
  <statement>  -> destroys <what>, recovery: <backup only | none>

BLOCKING
  <statement>  -> locks <table> (<n> rows) for approximately <estimate>
                  safe form: <rewrite>

INCOMPATIBLE WITH RUNNING CODE
  <statement>  -> <file:line> still reads this; split into expand/contract

SAFE
  <n> statements

VERDICT: safe to run | run in a maintenance window | must be split first

End with one verdict line. Someone is about to type a command and needs an answer, not a discussion.

Rules

  • Review the generated SQL, never the model diff.
  • A down migration restores schema, not data. Never call a drop reversible.
  • No lock warning without a row count; severity is row count.
  • Check compatibility with the CURRENTLY DEPLOYED code, not just the new code.
  • When a migration is genuinely safe, say so in one line. Hedging every review trains people to skip them.

From Toolbay. Free to use, modify, and share. Keep this line and others can find it too.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.