Overview
Diffing powers several critical features:- Migration generation (
migrate dev) - Diff Prisma schema vs. current database - Drift detection - Compare applied migrations vs. actual schema
- Schema comparison - Understand differences between environments
- Migration preview - See what will change before applying
Diffing is declarative - you define the desired end state, and the Schema Engine figures out how to get there.
How Diffing Works
The diffing process involves multiple steps:1. Load Schemas
Both “from” and “to” schemas are loaded into the internalDatabaseSchema representation. Sources can be:
- Prisma schema file - Parsed and converted to database schema
- Existing database - Introspected via connector
- Migration history - Applied to shadow database
- Empty schema - For initial migrations
2. Structural Comparison
The connector’s differ walks both schemas and identifies:- Added tables/columns/indexes
- Removed tables/columns/indexes
- Modified types, defaults, constraints
- Renamed entities
- Changed relationships
3. DDL Generation
Database-specific SQL is generated to effect the changes:4. Warning Detection
TheDestructiveChangeChecker analyzes changes for potential issues:
- Data loss (dropped tables/columns)
- Type changes that might fail
- Added non-nullable columns without defaults
- Constraint violations
The diff Command
Thediff method is exposed via JSON-RPC:
Diff Targets
Bothfrom and to can be:
1. Empty Schema
2. Schema Datasource
3. Schema Datamodel
4. Migration History
Migration Generation Workflow
When you runprisma migrate dev, here’s what happens:
Step 1: Determine Current State
The Schema Engine needs to know the current schema state:- Connect to shadow database (or create one)
- Apply all existing migrations to the shadow database
- Introspect the shadow database
- This introspected schema is the “from” state
Why use a shadow database?
Why use a shadow database?
The shadow database is necessary because:
- Migrations are black boxes (can contain arbitrary SQL)
- Schema Engine doesn’t parse SQL
- The only way to know what migrations do is to run them
- Running them on your dev database would be destructive
Step 2: Determine Desired State
The “to” schema comes from your Prisma schema file:- Parse the Prisma schema
- Convert it to the internal
DatabaseSchemarepresentation - This is the “to” state
Step 3: Generate Diff
Compare the two schemas:Migration object containing:
- DDL statements to execute
- Warnings about destructive changes
- Metadata about the changes
Step 4: Render Migration File
The migration is rendered as SQL:Step 5: Apply and Verify
The new migration is applied to your dev database and the shadow database is reset.Diff Output Formats
Summary Mode
Whenscript: false, returns a human-readable summary:
Script Mode
Whenscript: true, returns executable SQL:
Exit Codes
WhenexitCode: true:
0- No differences2- Differences detected
Destructive Changes
TheDestructiveChangeChecker identifies changes that might cause data loss or failures:
Warnings
- Dropped table: “You are about to drop the
Usertable. All data will be lost.” - Dropped column: “You are about to drop the column
emailon theUsertable. All data in the column will be lost.” - Type change: “You are changing the type of
agefromStringtoInt. This may fail if the data cannot be cast.”
Unexecutable Migrations
- Added non-nullable column without default: “Cannot add required column
emailwithout a default value to existing rows.” - Added unique constraint on non-unique data: “Cannot add unique constraint on
emailbecause duplicate values exist.”
Rename Detection
Diffing can detect renames vs. drop+create:Without Rename Tracking
With Rename Tracking
- Similar names (edit distance)
- Same type
- Position in table
- Annotations (
@map)
You can manually edit generated migrations to change DROP+CREATE into RENAME when the differ doesn’t detect it.
Database-Specific Diffing
Each connector implements its own differ:PostgreSQL
- Full DDL support
- Enums, arrays, composite types
- Advanced constraints
- Schema/namespace handling
MySQL
- Limited DDL (can’t modify multiple columns in one statement on older versions)
- No transactional DDL
- Storage engine considerations
SQL Server
- Schema-qualified names
- Different default handling
- Identity columns vs. sequences
SQLite
- Very limited ALTER TABLE support
- Often requires table recreation
- No DROP COLUMN before 3.35.0
MongoDB
- No traditional migrations
- Schema is implicit
- Limited diffing support
SQLite migration strategy
SQLite migration strategy
Because SQLite doesn’t support most ALTER TABLE operations, the differ generates:
- Create new table with desired schema
- Copy data from old table to new table
- Drop old table
- Rename new table to old name
- Recreate indexes and triggers
Schema Filters
TheSchemaFilter controls what’s compared:
- Multi-tenant databases
- Excluding non-Prisma tables
- Focusing on specific schemas
Implementation Details
Connector Trait
Key Files
- Diff command:
schema-engine/commands/src/commands/diff.rs - Connector trait:
schema-engine/connectors/schema-connector/src/diff.rs - SQL differ:
schema-engine/connectors/sql-schema-connector/src/sql_schema_differ/ - Destructive checker:
schema-engine/connectors/schema-connector/src/destructive_change_checker.rs
Best Practices
1. Review Generated Migrations
Always review migrations before committing:2. Handle Unexecutable Migrations
When adding non-nullable columns:3. Use Transactions
AddBEGIN; and COMMIT; to migrations when possible (see migrations guide).
4. Test in Staging
Always test migrations in a staging environment with production-like data before running in production.5. Preserve Custom SQL
Generated migrations can be edited to add:- Custom indexes
- Triggers
- Views
- Functions
- Row-level security policies
Comparison with Other Tools
vs. Liquibase/Flyway
Those tools require you to write migrations manually. Prisma:- ✅ Generates migrations automatically
- ✅ Detects schema changes
- ❌ Less control over exact SQL
vs. Entity Framework Migrations
Entity Framework is similar but:- Prisma uses actual database introspection (shadow DB)
- Entity Framework uses in-memory models
- Prisma handles arbitrary SQL in migrations
vs. Django Migrations
Django is similar but:- Django uses Python-based migrations
- Prisma uses SQL migrations
- Django’s migration graph is more complex
vs. db push
prisma db push is not migration-based:
- No migration files generated
- No history tracking
- Immediate schema sync
- Good for development, not for production
Related Documentation
Migration System
Learn how generated migrations are tracked and applied
Introspection
Understand how database schemas are read
Schema Engine Overview
High-level architecture and concepts