PrompTom
All skills

Migrating without losing data

db-migrationPROdatabasemigrations

Changes a schema so both the old and new code survive it — and so does a rollback.

What it does

  • Triggers on “add a column”, “rename this field”, “change the type”, “write a migration”.
  • Starts from the fact that old and new code overlap in production for minutes, and on a rollback for much longer. Everything else follows.
  • Splits a rename into four deploys: add, write to both, backfill, switch reads, drop later. A rename in one step breaks every running instance of the old code at once.
  • Puts a drop in a later deploy than the code that stopped using it. Otherwise a rollback leaves code expecting a column that is gone.
  • Asks the row count before, not after: a backfill over ten thousand rows is a statement, over ten million it is a batched job, or the lock takes the site down.
  • Requires the down migration to be written and read, and if the data cannot come back, to say so in the file itself — so the person at 3am knows before running it.
  • Verifies against a copy of production data: an empty database proves only that the syntax parsed.

Why you'd want it

Migrations do not break on syntax. They break because somebody forgot the five minutes when both versions of the code are live. Duplicates blocking a new unique constraint, nulls in a column about to be required, a lock on a large table — all of it is visible only on real data, and only if the question was asked in advance.

Where to put it

  1. 1Create the folder .claude/skills/db-migration in your project
  2. 2Put a SKILL.md file in it with the text below
  3. 3That's it. Claude Code loads the skill itself when a task matches the description

To make the skill available in every project rather than one, put it in ~/.claude/skills instead of the project folder.

SKILL.md file

# Changing a schema while the app is running

The old code and the new code overlap in production for at least a few
minutes, and on a rollback for much longer. Every migration must leave
both able to run.

That single constraint decides almost everything below.

## The safe shapes

**Adding a column:** nullable, or with a default. A `NOT NULL` column
with no default fails the moment old code inserts a row.

**Renaming:** never in one step. Add the new column, write to both,
backfill, switch reads, stop writing the old one, drop it later. Four
deploys, not one. A rename in a single migration breaks every running
instance of the old code at once.

**Changing a type:** the same shape as a rename. Widening (int to
bigint, varchar to text) is usually safe in place; narrowing never is.

**Dropping anything:** in a separate, later deploy from the code that

This skill's file is part of the PRO collection

Unlock access
Migrating without losing data — PrompTom