migrate-down
Enforces forward-only, multi-step schema changes to allow old and new code to run simultaneously.
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.zipInstalls 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.Key capabilities
- →Add new nullable columns in migration N
- →Backfill new columns in migration N+1 using SQL-only stubs
- →Switch application code reads to the new column
- →Remove old columns in migration N+2 after code deployment
- →Add NOT NULL constraints to existing nullable columns in multiple steps
How it works
This skill guides schema changes using the expand-contract policy, splitting non-additive modifications into multiple migrations and deployments to ensure old and new binaries can coexist.
Inputs & outputs
When to use migrate-down
- →Adding NOT NULL constraints to existing columns
- →Renaming database columns
- →Changing column data types
- →Splitting destructive DDL across releases
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.
- Add the new column (nullable) in migration N.
- Backfill the new column in migration N+1 (use
--sql-only—go run ./cmd/generate-migrations --sql-only --name=backfill_x). - Switch reads to the new column in the application code; deploy.
- Remove the old column in migration N+2.
DROP COLUMNis 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:
- Migration A: ADD COLUMN nullable, default-able.
- Deploy application code that always writes a non-null value for the new column (so all rows written after this deploy have a value).
- Migration B (
--sql-onlystub): BACKFILL existing null rows. - Migration C: ADD CONSTRAINT NOT NULL (or
ALTER COLUMN ... SET NOT NULL). - 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.
When not to use it
- →When attempting to roll back a migration using `migrate down`
- →When editing a committed migration file or its `atlas.sum`
- →When combining multiple schema changes into a single migration
Limitations
- →The migration tree is forward-only by design
- →It does not support `migrate down` operations
- →It requires schema changes to be split across multiple deploys
How it compares
This workflow enforces a forward-only migration tree and the expand-contract policy to prevent rollbacks and ensure schema safety, unlike direct schema modifications or `migrate down` approaches.
Compared to similar skills
migrate-down side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| migrate-down (this skill) | 0 | 2mo | No flags | Advanced |
| supabase | 1 | 4mo | Review | Intermediate |
| drizzle-orm | 32 | 2mo | No flags | Intermediate |
| database-design | 6 | 6mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by kalbasit
View all by kalbasit →You might also like
supabase
alinaqi
Core Supabase CLI, migrations, RLS, Edge Functions
drizzle-orm
EpicenterHQ
Drizzle ORM patterns for type branding and custom types. Use when working with Drizzle column definitions, branded types, or custom type conversions.
database-design
davila7
Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases.
database-schema-designer
davila7
Design robust, scalable database schemas for SQL and NoSQL databases. Provides normalization guidelines, indexing strategies, migration patterns, constraint design, and performance optimization. Ensures data integrity, query performance, and maintainable data models.
supabase-policy-guardrails
jeremylongshore
Implement Supabase lint rules, policy enforcement, and automated guardrails. Use when setting up code quality rules for Supabase integrations, implementing pre-commit hooks, or configuring CI policy checks for Supabase best practices. Trigger with phrases like "supabase policy", "supabase lint", "supabase guardrails", "supabase best practices check", "supabase eslint".
database-migrations-sql-migrations
sickn33
SQL database migrations with zero-downtime strategies for PostgreSQL, MySQL, SQL Server