prisma-migration-reviewer
npx machina-cli add skill Nembie/claude-code-skills/prisma-migration-reviewer --openclawPrisma Migration Reviewer
Before generating any output, read config/defaults.md and adapt all patterns, imports, and code examples to the user's configured stack.
Process
- Read the
migration.sqlfile (typically atprisma/migrations/<timestamp>_<name>/migration.sql). - Parse each SQL statement and classify it by risk level.
- Identify data loss risks, breaking changes, performance concerns, and missing safeguards.
- Suggest safer alternatives for dangerous operations.
- Produce a risk report with actionable recommendations.
Risk Classification
CRITICAL — Data Loss Risk
These operations destroy data. Block deployment until reviewed.
Column drop:
-- CRITICAL: Drops column and all its data
ALTER TABLE "User" DROP COLUMN "legacyId";
Safe alternative: Rename to _deprecated_legacyId, drop in a later migration after confirming no code references it.
Table drop:
-- CRITICAL: Drops table and all rows
DROP TABLE "OldAuditLog";
Safe alternative: Rename table to _archived_OldAuditLog. Drop after data is verified migrated or backed up.
Type change with data loss:
-- CRITICAL: Changing TEXT to VARCHAR(50) truncates values longer than 50 chars
ALTER TABLE "Post" ALTER COLUMN "title" TYPE VARCHAR(50);
Safe alternative: First query SELECT MAX(LENGTH(title)) FROM "Post" to verify no data exceeds the new limit.
Enum value removal:
-- CRITICAL: Rows with removed value become invalid
-- Prisma recreates enum without the old value
CREATE TYPE "Role_new" AS ENUM ('USER', 'ADMIN');
ALTER TABLE "User" ALTER COLUMN "role" TYPE "Role_new" USING ("role"::text::"Role_new");
DROP TYPE "Role";
ALTER TYPE "Role_new" RENAME TO "Role";
Safe alternative: First update all rows with the old value, then remove it.
WARNING — Potential Downtime or Breakage
NOT NULL on existing column without default:
-- WARNING: Fails if any existing rows have NULL in this column
ALTER TABLE "User" ALTER COLUMN "name" SET NOT NULL;
Safe alternative:
UPDATE "User" SET "name" = 'Unknown' WHERE "name" IS NULL;- Then
ALTER TABLE "User" ALTER COLUMN "name" SET NOT NULL;
Adding unique constraint on column with potential duplicates:
-- WARNING: Fails if duplicate values exist
ALTER TABLE "User" ADD CONSTRAINT "User_email_key" UNIQUE ("email");
Safe alternative: First query SELECT email, COUNT(*) FROM "User" GROUP BY email HAVING COUNT(*) > 1 and resolve duplicates.
Renaming column (Prisma drops and recreates):
-- WARNING: Prisma may generate DROP + ADD instead of RENAME, losing data
ALTER TABLE "User" DROP COLUMN "name";
ALTER TABLE "User" ADD COLUMN "fullName" TEXT;
Safe alternative: Use raw SQL migration with ALTER TABLE "User" RENAME COLUMN "name" TO "fullName".
Large table ALTER:
-- WARNING: On tables with millions of rows, this acquires an exclusive lock
ALTER TABLE "Event" ADD COLUMN "metadata" JSONB;
For PostgreSQL, adding a nullable column with no default is fast (no table rewrite). But adding a column with a DEFAULT requires a table rewrite on PostgreSQL < 11.
INFO — Optimization Opportunities
Missing index on foreign key:
ALTER TABLE "Post" ADD COLUMN "authorId" TEXT NOT NULL;
ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey"
FOREIGN KEY ("authorId") REFERENCES "User"("id");
-- INFO: No index on "Post"."authorId" — queries filtering/joining on this FK will be slow
Recommend: CREATE INDEX "Post_authorId_idx" ON "Post"("authorId");
Missing composite index for common query patterns:
-- INFO: If queries often filter by both status and createdAt, add a composite index
CREATE INDEX "Order_status_createdAt_idx" ON "Order"("status", "createdAt");
Prisma-Specific Gotchas
- Prisma renames = drop + create: When you rename a field in
schema.prisma, Prisma generates a column drop and add, not a rename. Always usenpx prisma migrate --create-onlyand edit the SQL to useRENAME COLUMN. - Enum changes recreate the type: Any change to a Prisma enum generates a full drop-and-recreate cycle. Inspect the migration to ensure existing data is preserved.
- Optional → required: Changing a field from
String?toStringgeneratesSET NOT NULLwithout a backfill. Always add a backfill step. - Relation changes: Changing relation cardinality or required-ness can drop and recreate foreign key constraints, potentially orphaning data.
Checklist
Before approving any migration:
- No
DROP COLUMNorDROP TABLEwithout confirmed backup or rename strategy - No
SET NOT NULLwithout backfill for existing NULL rows - No
UNIQUEconstraint on columns with unverified uniqueness - All foreign key columns have indexes
- Column renames use
RENAME COLUMN, not drop + add - Enum changes preserve existing data values
- Large table operations assessed for lock duration
- Down migration strategy documented for irreversible operations
Output Format
## Migration Review: `<migration_name>`
### Summary
| Risk Level | Count |
|-----------|-------|
| 🔴 CRITICAL | N |
| 🟡 WARNING | N |
| 🔵 INFO | N |
### Findings
#### 🔴 CRITICAL: [Title]
**Statement**: `[SQL statement]`
**Risk**: [What can go wrong]
**Recommendation**: [Safer alternative with SQL]
#### 🟡 WARNING: [Title]
...
#### 🔵 INFO: [Title]
...
### Pre-Deploy Checklist
- [ ] [Actionable step based on findings]
Reference
See references/migration-risks.md for the complete catalog of dangerous operations and zero-downtime patterns.
Source
git clone https://github.com/Nembie/claude-code-skills/blob/main/skills/prisma-migration-reviewer/SKILL.mdView on GitHub Overview
Prisma Migration Reviewer analyzes migration.sql files to identify data loss, breaking changes, and performance risks. It classifies risks, suggests safer alternatives, and outputs a practical risk report tailored to your stack by consulting defaults.md first.
How This Skill Works
It reads the migration.sql file, parses each SQL statement, and classifies risk levels (CRITICAL, WARNING, INFO). It then highlights data loss risks, breaking changes, and performance concerns, proposing safer alternatives and generating an actionable risk report.
When to Use It
- Before deploying a Prisma migration to production
- When a migration may cause data loss or breaking schema changes
- When enum changes or type alterations could impact data integrity
- When performance or downtime risks are anticipated due to large migrations
- When auditing Prisma migrations for safety and compliance
Quick Start
- Step 1: Locate the migration SQL file at prisma/migrations/<timestamp>_<name>/migration.sql
- Step 2: Parse statements, classify risk (CRITICAL, WARNING, INFO), and identify data loss or downtime risks
- Step 3: Generate a risk report with actionable recommendations and safer alternatives
Best Practices
- Always review CRITICAL risks first and block deploys when present
- Prefer safe alternatives (renames, backups, or staged changes) over destructive operations
- Verify NOT NULL changes with defaults or data cleanup before applying
- Check for missing indexes on FKs or commonly filtered columns
- Test migrations in a staging environment that mirrors production data
Example Use Cases
- Migration drops a column and is flagged CRITICAL; use a rename strategy or archival migration before removal
- Not NULL on an existing column without default; plan a two-step fix: set default values, then enforce NOT NULL
- Adding a unique constraint on a column with possible duplicates; detect duplicates and resolve before applying
- Column rename triggers drop and add in Prisma; use a SQL rename alternative to avoid data loss
- Large table alteration risks downtime; prefer adding nullable columns first or perform in batches with proper indexes