From caio-build-harness
Patterns for Prisma migrate dev workflow, expand-contract zero-downtime schema changes, rollback procedures, and coordinating migrations across team members. Use for any schema change — not for query optimization or ORM setup.
How this skill is triggered — by the user, by Claude, or both
Slash command
/caio-build-harness:database-migrationsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Reference this skill when:
Reference this skill when:
# After modifying prisma/schema.prisma:
bunx prisma migrate dev --name descriptive_name
# Examples:
bunx prisma migrate dev --name add_user_table
bunx prisma migrate dev --name add_training_plan_status_field
bunx prisma migrate dev --name create_workout_log_index
YYYYMMDDHHMMSS_descriptive_name
Examples:
20240115120000_add_user_table
20240115130000_add_training_plan_relations
20240116090000_add_status_enum_to_plans
add_, create_, remove_, rename_, update_add_email_to_users not update_users// Safe: nullable column with default
model User {
id String @id @default(cuid())
email String @unique
name String?
// NEW: safe because nullable
avatarUrl String?
}
// Step 1: Add as nullable
model User {
status String?
}
// Step 2: Backfill data
// In a migration SQL file:
// UPDATE "User" SET "status" = 'active' WHERE "status" IS NULL;
// Step 3: Make required (separate migration)
model User {
status String @default("active")
}
-- DANGER: Prisma doesn't detect renames — it drops and creates
-- Use raw SQL migration instead:
ALTER TABLE "User" RENAME COLUMN "name" TO "displayName";
1. Remove all code references first
2. Deploy code that doesn't use the column
3. Then remove from schema and migrate
4. Never remove column and code in same deploy
// Safe: non-blocking in PostgreSQL
model WorkoutLog {
id String @id @default(cuid())
userId String
createdAt DateTime @default(now())
@@index([userId, createdAt])
}
// Safe: adding a new value
enum PlanStatus {
DRAFT
ACTIVE
COMPLETED
ARCHIVED // NEW: safe to add
}
// DANGEROUS: removing or renaming a value
// Must backfill existing rows first
Phase 1: EXPAND (add new, keep old)
- Add new column/table
- Deploy code that writes to BOTH old and new
- Backfill new from old
Phase 2: MIGRATE (switch reads)
- Deploy code that reads from new
- Verify correctness
Phase 3: CONTRACT (remove old)
- Deploy code that only uses new
- Remove old column/table in separate migration
name to displayNameStep 1: Add displayName (nullable)
Step 2: Deploy code that writes to both name AND displayName
Step 3: Backfill: UPDATE "User" SET "displayName" = "name" WHERE "displayName" IS NULL
Step 4: Deploy code that reads from displayName
Step 5: Make displayName required
Step 6: Deploy code that stops writing to name
Step 7: Remove name column
# Always create a backup point
pg_dump $DATABASE_URL > backup_$(date +%Y%m%d_%H%M%S).sql
# Or use Prisma's built-in
bunx prisma migrate diff \
--from-schema-datamodel prisma/schema.prisma \
--to-migrations prisma/migrations \
--script > rollback.sql
# Option 1: Prisma migrate (if migration hasn't been applied to prod)
bunx prisma migrate resolve --rolled-back MIGRATION_NAME
# Option 2: Manual SQL rollback
psql $DATABASE_URL < rollback.sql
# Option 3: Full restore (nuclear option)
psql $DATABASE_URL < backup_TIMESTAMP.sql
Rule: ONE engineer owns the schema per sprint/phase.
Why: Concurrent schema changes create unmergeable migration conflicts.
How:
- Ticket schema changes are assigned to one person
- Other engineers request schema changes via ticket comments
- Schema owner batches and creates migrations
# When two engineers create migrations on different branches:
# Engineer B (has conflict):
1. Delete their local migration folder
2. Pull main (gets Engineer A's migration)
3. Re-run: bunx prisma migrate dev --name their_change
4. This creates a new migration AFTER Engineer A's
Before merging a migration PR:
# 1. Verify migration in staging first
bunx prisma migrate deploy # on staging
# 2. Check migration status
bunx prisma migrate status
# 3. Backup production
pg_dump $DATABASE_URL > pre_migration_backup.sql
# 4. Run migration
bunx prisma migrate deploy # on production
# 5. Verify
bunx prisma migrate status
# Test critical queries
# 6. Monitor
# Watch error rates for 15 minutes
# Check query performance
npx claudepluginhub get-caio/harness --plugin caio-build-harnessProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.