Skip to main content

Migrations

UniPulse uses Prisma Migrate to manage database schema changes. All migrations are stored as SQL files in apps/api/prisma/migrations/ and applied in order.


Migration Workflow


Creating a Migration

After modifying apps/api/prisma/schema.prisma:

cd apps/api
npx prisma migrate dev --name describe_your_change

This will:

StepAction
1Diff the schema against the current database state
2Generate a timestamped SQL migration in prisma/migrations/
3Apply the migration to your local PostgreSQL database
4Regenerate the Prisma client with updated types

Migration File Structure

apps/api/prisma/migrations/
├── 20260101000000_initial_schema/
│ └── migration.sql
├── 20260115000000_add_audience_segments/
│ └── migration.sql
├── 20260201000000_add_revenue_attribution/
│ └── migration.sql
└── migration_lock.toml

Applying Migrations in Production

# In the production environment (or Docker container)
npx prisma migrate deploy

This applies all pending migrations without generating new ones. It is safe to run multiple times -- already-applied migrations are skipped.

# Via Docker Compose
docker compose exec api npx prisma migrate deploy

Checking Migration Status

npx prisma migrate status

Shows which migrations have been applied and which are pending.


Resetting the Database

npx prisma migrate reset
Data Loss

This drops all tables and data, then re-applies all migrations from scratch. Only use in development environments. Never run this in production.


Common Migration Operations

Adding a New Model

// schema.prisma
model CouponGenerated {
id String @id @default(cuid())
workspaceId String
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
code String
discount Float
usageCount Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@index([workspaceId])
}
npx prisma migrate dev --name add_coupon_generated

Adding a Field to an Existing Model

model Post {
// ... existing fields
sentimentScore Float? // New nullable field
}
npx prisma migrate dev --name add_sentiment_score_to_post

Adding an Index

model PostMetric {
// ... existing fields

@@index([publicationId, date]) // New composite index
}
npx prisma migrate dev --name add_index_post_metric_date

Renaming a Field (Requires Custom SQL)

Prisma cannot auto-detect renames. You need to create a custom migration:

npx prisma migrate dev --name rename_field --create-only

Then edit the generated SQL:

-- Instead of DROP + ADD, use ALTER COLUMN RENAME
ALTER TABLE "Post" RENAME COLUMN "old_name" TO "new_name";

Then apply:

npx prisma migrate dev

Migration Best Practices

PracticeWhy
Name migrations descriptivelyadd_audience_segments, add_index_on_post_created_at
Review generated SQL before committingCatch unintended schema changes
Never edit applied migration filesBreaks migration history
Test on staging before productionCatch issues before they affect live data
Back up database before production migrationsSafety net for rollbacks
Add workspaceId + index to new modelsMaintains multi-tenant isolation
Use onDelete: Cascade thoughtfullyPrevent orphaned records but avoid cascade surprises
Make new fields nullable or provide defaultsAvoids migration failures on existing data

Seeding

For development data seeding:

npx prisma db seed

The seed script is defined in apps/api/prisma/seed.ts and creates sample workspaces, users, posts, and other test data.


Cross-Reference