15.5 Prisma Migrations — Schema Management and Seeding
Migration Workflow
Development flow:
1. Modify schema.prisma
2. npx prisma migrate dev → Create migration file + apply to DB
3. npx prisma generate → Regenerate Prisma Client (automatic)
4. Commit migration files to git
Deployment flow:
1. git pull (with migration files)
2. npx prisma migrate deploy → Apply only unapplied migrations in order
Migration Commands
# Development — create and apply migration
npx prisma migrate dev --name add-user-avatar
# Check migration history
npx prisma migrate status
# Production deployment (use in CI/CD)
npx prisma migrate deploy
# Reset dev DB (re-runs all migrations from scratch)
npx prisma migrate reset
# Rollback specific migration (not supported — requires manual SQL)
Example Generated Migration File
-- prisma/migrations/20240115000000_add_user_avatar/migration.sql
-- AlterTable
ALTER TABLE "User" ADD COLUMN "avatar" TEXT;
ALTER TABLE "User" ADD COLUMN "avatarUpdatedAt" TIMESTAMP(3);
Schema Change Patterns
Add Column (Safe)
model User {
// Existing fields...
avatar String? // Nullable — no impact on existing data
bio String @default("") // Set default value
}
Rename Column
model User {
// Rename firstName → name
// Direct rename causes data loss! Use @map
name String @map("firstName") // Keep DB column name, change Prisma accessor
}
Delete Column (Caution)
// Step 1: Remove references to the field in application code
// Step 2: Make nullable and deploy
// Step 3: Run actual column drop migration
Rename Table
model Article {
@@map("Post") // DB table name is "Post", Prisma model name is "Article"
}
Data Seeding
// prisma/seed.ts
import { PrismaClient } from '@prisma/client'
import * as bcrypt from 'bcrypt'
const prisma = new PrismaClient()
async function main() {
// Clean up existing data (optional)
await prisma.post.deleteMany()
await prisma.user.deleteMany()
// Create admin account
const admin = await prisma.user.create({
data: {
email: 'admin@example.com',
name: 'Admin',
password: await bcrypt.hash('adminpassword', 10),
role: 'ADMIN',
},
})
// Create regular users with posts
const users = await Promise.all(
Array.from({ length: 5 }, (_, i) =>
prisma.user.create({
data: {
email: `user${i + 1}@example.com`,
name: `User ${i + 1}`,
password: await bcrypt.hash('password', 10),
posts: {
create: Array.from({ length: 3 }, (_, j) => ({
title: `User ${i + 1} Post ${j + 1}`,
content: `Content ${j + 1}`,
published: j < 2, // First 2 posts published
})),
},
},
})
)
)
console.log(`Created ${users.length} users`)
}
main()
.catch(console.error)
.finally(async () => {
await prisma.$disconnect()
})
Configure Seed in package.json
{
"prisma": {
"seed": "tsx prisma/seed.ts"
},
"devDependencies": {
"tsx": "^4.0.0"
}
}
# Run seed
npx prisma db seed
# Reset migrations + auto-run seed
npx prisma migrate reset
Per-Environment Database Configuration
# .env (development)
DATABASE_URL="postgresql://user:password@localhost:5432/myapp_dev"
# .env.test (test environment)
DATABASE_URL="postgresql://user:password@localhost:5432/myapp_test"
# .env.production (production)
DATABASE_URL="postgresql://user:password@prod-db:5432/myapp_prod?connection_limit=10&pool_timeout=20"
Pro Tips
Schema Validation and Formatting
# Validate schema syntax
npx prisma validate
# Format schema file
npx prisma format
# Generate ERD diagram (requires prisma-erd-generator)
npx prisma generate # Auto-generates ERD.svg
CI/CD Pipeline Configuration
# .github/workflows/deploy.yml
jobs:
deploy:
steps:
- name: Apply migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
- name: Generate Prisma Client
run: npx prisma generate
Split Prisma Schema (Large Projects)
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["prismaSchemaFolder"]
}
// prisma/schema/user.prisma — Split models into separate files (Preview feature)
model User {
id Int @id
email String @unique
}