Skip to main content
Advertisement

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
}
Advertisement