| name | prisma-migration |
| description | Create a Prisma migration file for schema changes. Required for production — db push only works in dev. Use after modifying schema.prisma. |
| argument-hint | <migration-name> |
Prisma Migration Generator
Create a migration for: $ARGUMENTS
Why This Matters
- Production uses
prisma migrate deploy which ONLY applies migration files
- Dev uses
prisma db push (no migration files needed for iteration)
- Every schema change MUST have a migration file before merging to main
- Forgetting this means schema changes silently don't apply in production
Migration File Structure
Naming convention (sequential numbering):
prisma/migrations/NNNN_description/migration.sql
Check prisma/migrations/ for the latest number and increment by 1.
Common SQL Patterns
Add column:
ALTER TABLE "TableName" ADD COLUMN "columnName" TEXT;
Add column with default:
ALTER TABLE "TableName" ADD COLUMN "columnName" BOOLEAN NOT NULL DEFAULT false;
Add array column (PostgreSQL):
ALTER TABLE "TableName" ADD COLUMN "columnName" TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[];
Add index:
CREATE INDEX "TableName_columnName_idx" ON "TableName"("columnName");
Add unique constraint:
ALTER TABLE "TableName" ADD CONSTRAINT "TableName_columnName_key" UNIQUE ("columnName");
Create new table:
The project's models use id String @id @default(cuid()) — cuids are generated
app-side by Prisma, so the id column has NO database-level default (do NOT use
gen_random_uuid(); no existing migration does). This matches every table in
0001_init.
CREATE TABLE "TableName" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "TableName_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "TableName_userId_idx" ON "TableName"("userId");
ALTER TABLE "TableName" ADD CONSTRAINT "TableName_userId_fkey"
FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
Create enum:
CREATE TYPE "EnumName" AS ENUM ('VALUE1', 'VALUE2');
Add enum value:
ALTER TYPE "EnumName" ADD VALUE 'NEW_VALUE';
Drop column:
ALTER TABLE "TableName" DROP COLUMN "columnName";
Steps
- Check
prisma/migrations/ to determine the next migration number
- Update
prisma/schema.prisma with the schema changes
- Create
prisma/migrations/NNNN_$ARGUMENTS/migration.sql with the SQL
- Push schema to dev DB:
pnpm docker:dev:db:push
- Mark migration as already applied on dev DB:
DATABASE_URL="postgresql://librariarr:librariarr@localhost:5432/librariarr" pnpm exec prisma migrate resolve --applied NNNN_$ARGUMENTS
- Verify migration status:
DATABASE_URL="postgresql://librariarr:librariarr@localhost:5432/librariarr" pnpm exec prisma migrate status
Should show "Database schema is up to date!"
- Regenerate Prisma client:
pnpm exec prisma generate
Post-Migration Checklist
- If adding a new table: add
deleteMany() call to tests/setup/test-db.ts cleanDatabase() in correct dependency order
- If adding a table with user data: consider adding to
src/lib/backup/backup-service.ts
- If adding a table that needs test data: add a factory function to
tests/setup/test-helpers.ts