drizzle-migration-safety
Safe Drizzle ORM migration patterns for PostgreSQL. Auto-loads on migration files. Mandatory reading before writing or editing a migration.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Safe Drizzle ORM migration patterns for PostgreSQL. Auto-loads on migration files. Mandatory reading before writing or editing a migration.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | drizzle-migration-safety |
| description | Safe Drizzle ORM migration patterns for PostgreSQL. Auto-loads on migration files. Mandatory reading before writing or editing a migration. |
| globs | ["drizzle/**/*.sql","drizzle/migrations/**/*"] |
| allowed-tools | Read, Write, Edit, Grep, Glob, Bash(pnpm:*) |
Migrations affect production data. Drizzle has NO down migrations — forward-only SQL. A bad migration cannot be undone by git revert. It can be undone only by writing another migration. Slow down here.
# 1. Modify Drizzle model in src/modules/*/*.model.ts
# 2. Generate migration SQL
pnpm db:generate
# 3. Review the generated SQL in drizzle/migrations/
# 4. Run /migration command to invoke drizzle-migration-reviewer
# 5. If approved: apply
pnpm db:migrate
# For dev only (no migration file, direct push):
pnpm db:push
NEVER do this in one migration:
-- WRONG: fails on existing rows with NULL
ALTER TABLE users ALTER COLUMN email SET NOT NULL;
DO this in two separate migrations + a backfill:
Migration 1 — Add column as nullable (or ensure it's already nullable)
Backfill — Update existing NULL rows:
UPDATE users SET email = 'legacy-' || id || '@unknown.local' WHERE email IS NULL;
Migration 2 — Alter to NOT NULL:
ALTER TABLE users ALTER COLUMN email SET NOT NULL;
Each migration deploys separately. Verify backfill in production before applying Migration 2.
Always use CONCURRENTLY for PostgreSQL:
CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders(user_id);
Without CONCURRENTLY, PostgreSQL locks the table for writes during index creation.
NEVER rename in one step. Use expand-contract across multiple deploys:
Always pair FK with an index on the FK column:
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
ALTER TABLE orders ADD CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers(id);
Always: deleted_at TIMESTAMP NULL (matches Drizzle model deletedAt).
down(). Be extra cautious.drizzle-migration-reviewer agent before committing (enforced by hook)pre-edit-guards.sh hook blocks direct edits to drizzle/migrations/ without .claude/.migration-approvedpnpm db:push in production (use pnpm db:migrate)Awilix dependency injection patterns for this Fastify project — auto-loading conventions, Cradle usage, partial application, type declarations.
CQS (Command Query Separation) patterns — mutations for writes with events, queries for reads without side effects.
Drizzle ORM query patterns for this project — base repository, soft delete, NON_PASSWORD_COLUMNS, query builder conventions.
Fastify route handler patterns — TypeBox validation, DI access, schema definitions, JWT guards, error handling conventions.
E2E testing patterns using Node.js native test runner — createTestingApp, createDbHelper, factories, app.inject() for HTTP testing.