agentskills.codes
MI

migrate-down

Roll back a migration — DON'T. Use the expand-contract policy.

Install

mkdir -p .claude/skills/migrate-down && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14137" && unzip -o skill.zip -d .claude/skills/migrate-down && rm skill.zip

Installs to .claude/skills/migrate-down

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Roll back a migration — DON'T. Use the expand-contract policy.
62 charsno explicit “when” trigger

About this skill

There Is No migrate down

ncps migrate down exits non-zero with ErrDownNotSupported. The migration tree is forward-only by design — every .sql file under migrations/<dialect>/ is sealed by atlas.sum, the runtime only applies (goose.Up), and no operator-facing rollback is provided.

This rules out the entire class of "fix it by reverting" patterns that mid-deployment column rewrites depend on. To change schema safely, use the expand-contract policy instead.

Expand-contract policy

Column changes that aren't purely additive — type changes, NOT NULL additions, renames — must be split across multiple deploys so old and new binaries can coexist against the same schema.

  1. Add the new column (nullable) in migration N.
  2. Backfill the new column in migration N+1 (use --sql-onlygo run ./cmd/generate-migrations --sql-only --name=backfill_x).
  3. Switch reads to the new column in the application code; deploy.
  4. Remove the old column in migration N+2. DROP COLUMN is flagged as sensitive DDL by the migration spec and is only permissible at this final step, once no deployed binary references the old column.

Each migration ships in its own release; the application gracefully handles the dual-column state in between.

Four-step NOT NULL recipe

The specific case of adding a NOT NULL constraint to an existing nullable column:

  1. Migration A: ADD COLUMN nullable, default-able.
  2. Deploy application code that always writes a non-null value for the new column (so all rows written after this deploy have a value).
  3. Migration B (--sql-only stub): BACKFILL existing null rows.
  4. Migration C: ADD CONSTRAINT NOT NULL (or ALTER COLUMN ... SET NOT NULL).
  5. Deploy each step independently; never combine into a single migration.

What if I really really need to undo?

You don't. Migrations are sealed; the only path "backward" is forward — a new migration that reverses the intent of the previous one. If the schema is genuinely broken, restore from backup; never edit a committed migration file or its atlas.sum.

See CLAUDE.md and openspec/specs/data-model/spec.md for the rationale and additional context.

Search skills

Search the agent skills registry