Schema diffing is the process of comparing two database schemas and generating the SQL statements needed to transform one into the other. This is the core mechanism behind Prisma Migrate’s declarative workflow.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/prisma/prisma-engines/llms.txt
Use this file to discover all available pages before exploring further.
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