The braindead mistake that'll get you fired faster than using Comic Sans in presentations: running `prisma migrate dev` in production. Mix these up and you'll be explaining to your boss why user data vanished into the digital void.
Development Workflow: prisma migrate dev
In your local development environment, prisma migrate dev
automatically handles three operations:
- Generates migration files from schema changes
- Applies migrations to your database
- Regenerates the Prisma client
## Development - generates AND applies migrations
npx prisma migrate dev --name add-user-preferences
This command creates migration files in prisma/migrations/
and immediately applies them to your development database. Perfect for iteration, absolutely fucking dangerous for production.
Production Workflow: prisma migrate deploy
Production uses `prisma migrate deploy` which only applies existing migrations. It never generates new migration files. No surprises, no new files generated. Just runs what you tested locally.
## Production - applies existing migrations only
npx prisma migrate deploy
I once used migrate dev
in production because I was half-asleep during a Friday deployment. Deleted a column that was still in use and had to explain to HR why the site was down.
OK, here's why that command was wrong: migrate deploy
only reads existing migration files from your repo and applies the ones that haven't run yet. If migration files don't exist, deployment fails and you get to explain to your team why the deploy is broken.
The Correct Production Deployment Process
First, create migrations locally without applying them:
## Generate migration without applying it
npx prisma migrate dev --create-only --name optimize-user-queries
This creates the migration file for review without changing your local database. The `--create-only` flag generates migration files without applying them.
Next, review the SQL that Prisma generated. Migration files live in prisma/migrations/[timestamp]_[name]/migration.sql
. Always check the SQL before deployment:
-- Generated migration example
-- Migration: 20250921000000_optimize_user_queries
-- CreateIndex
CREATE INDEX "User_email_verified_idx" ON "User"("email", "verified");
-- AlterTable
ALTER TABLE "User" ADD COLUMN "preferences" JSONB;
Apply locally for testing:
## Apply the reviewed migration locally
npx prisma migrate dev
Commit migration files:
git add prisma/migrations/
git commit -m "Add user preferences and email index"
Deploy to production through your CI/CD pipeline:
npx prisma migrate deploy
npx prisma generate
Why This Process Matters
Production migrations are irreversible, unlike your career after you DROP TABLE Users. The review step catches destructive changes before they reach user data.
The same migration files apply identically across staging and production environments. No surprises.
Migration files in version control give you complete schema change history. Blame is trackable.
Environment Variables for Production
Production deployments require specific environment setup:
## Production DATABASE_URL
DATABASE_URL="postgresql://user:pass@prod-host:5432/app?sslmode=require&connection_limit=20"
## Required for migrate deploy
PRISMA_MIGRATE_SKIP_GENERATE=true # Skip client generation during migration
Connection limits matter: Production databases need connection pooling. Without connection_limit=20
, your database will die faster than your hopes of a peaceful deployment.
We learned this the hard way when our monitoring showed 500 dead connections and angry users flooding customer support. The migration succeeded, but the database was too overwhelmed to serve traffic for 20 minutes.
CI/CD Integration Best Practices
Most deployment failures happen because teams run migrations manually. Automated deployment pipelines prevent human error:
## Example GitHub Actions deployment
- name: Run Database Migration
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
- name: Generate Prisma Client
run: npx prisma generate
Deploy order matters: Always run migrate deploy
before `prisma generate`. Client generation needs the updated database schema.
When Deployments Fail
The most common production deployment error:
Error: P3005 The database schema is not empty.
Read more about how to baseline an existing production database
This happens when deploying Prisma Migrate to an existing database. The solution is database baselining, covered in the troubleshooting section below.
Never run `prisma db push` in production. This command bypasses migration history and can cause irreversible schema drift between environments. You'll regret it.