database-migrations ยท git:20260610.5639e7f ยท 2026-06-10 ยท sha256 a205d0413acaa009

database-migrations git:20260610.5639e7fA

Immutable. This exact content never changes and is served at /api/v1/blob/a205d0413acaa009.

---
name: database-migrations
description: Database migration best practices for schema changes, data migrations, rollbacks, and zero-downtime deployments across PostgreSQL, MySQL, and common ORMs (Prisma, Drizzle, Kysely, Django, TypeORM, golang-migrate).
mcp: code-review-graph
---

# /supergraph:database-migrations

Safe, reversible database schema changes for production systems.

Announce: "๐Ÿ—„๏ธ /supergraph:database-migrations โ€” checking blast radius and migration safety..."

## When to Activate

- Creating or altering database tables
- Adding/removing columns or indexes
- Running data migrations (backfill, transform)
- Planning zero-downtime schema changes
- Setting up migration tooling for a new project

## Steps

### 1. Check blast radius (MANDATORY before writing any migration)
```
mcp__code-review-graph__get_impact_radius_tool(files=[schema_files, model_files], depth=2)
mcp__code-review-graph__query_graph_tool(query_type="dependents", target=<schema_file>)
```
Schema changes to hub tables (e.g. `users`, `orders`) ripple through repositories, queries, services. If blast radius > 20 files โ†’ STOP and discuss with user.

**Serena symbol-level impact (optional):**
```
mcp__serena__find_referencing_symbols(symbol=<column_or_model_name>)
```
Finds ORM field references that graph tools see only at file level โ€” e.g. a Prisma field rename that `query_graph` sees as "file touched" but Serena sees as "12 usages in service layer". Skip if Serena unavailable.

### 2. Choose migration pattern
Select the appropriate pattern from the sections below (PostgreSQL, Prisma, Drizzle, etc.) based on detected project type from `.supergraph-env`.

### 3. Write migration
Follow Migration Safety Checklist before writing SQL/ORM migration code.

### 4. Verify flows
After migration written:
```
mcp__code-review-graph__get_affected_flows_tool(files=[migration_and_related_code])
```
All data flows still intact? Application code updated to match schema?

### 5. Report
```
โœ… /supergraph:database-migrations
- Pattern: [expand-contract | add-column | add-index | data-migration | ...]
- Blast radius: N files | Hub tables: [list/none]
- Safety checklist: PASS | BLOCKED (list issues)
- Next: /supergraph:tdd โ†’ /supergraph:fix โ†’ /supergraph:verify
```

## Core Principles

1. **Every change is a migration** โ€” never alter production databases manually
2. **Migrations are forward-only in production** โ€” rollbacks use new forward migrations
3. **Schema and data migrations are separate** โ€” never mix DDL and DML in one migration
4. **Test migrations against production-sized data** โ€” a migration that works on 100 rows may lock on 10M
5. **Migrations are immutable once deployed** โ€” never edit a migration that has run in production

## Migration Safety Checklist

Before applying any migration:

- [ ] Migration has both UP and DOWN (or is explicitly marked irreversible)
- [ ] No full table locks on large tables (use concurrent operations)
- [ ] New columns have defaults or are nullable (never add NOT NULL without default)
- [ ] Indexes created concurrently (not inline with CREATE TABLE for existing tables)
- [ ] Data backfill is a separate migration from schema change
- [ ] Tested against a copy of production data
- [ ] Rollback plan documented

> Full ORM examples (PostgreSQL, Prisma, Drizzle, Kysely, Django, golang-migrate): [REFERENCE.md](./REFERENCE.md)

## Anti-Patterns

| Anti-Pattern                         | Why It Fails                         | Better Approach                             |
| ------------------------------------ | ------------------------------------ | ------------------------------------------- |
| Manual SQL in production             | No audit trail, unrepeatable         | Always use migration files                  |
| Editing deployed migrations          | Causes drift between environments    | Create new migration instead                |
| NOT NULL without default             | Locks table, rewrites all rows       | Add nullable, backfill, then add constraint |
| Inline index on large table          | Blocks writes during build           | CREATE INDEX CONCURRENTLY                   |
| Schema + data in one migration       | Hard to rollback, long transactions  | Separate migrations                         |
| Dropping column before removing code | Application errors on missing column | Remove code first, drop column next deploy  |

## Rules

- ALWAYS check blast radius before writing any migration โ€” hub table changes need user approval
- NEVER alter production databases manually โ€” every change goes through migration files
- NEVER mix DDL and DML in one migration โ€” separate schema changes from data migrations
- NEVER add NOT NULL column without a default to existing tables โ€” locks and rewrites all rows
- ALWAYS create indexes with CONCURRENTLY on live tables
- ALWAYS test against production-sized data before deploying
- NEVER edit a migration that has already run in production โ€” create a new one
- Use expand-contract pattern for zero-downtime column renames and removals