Getting Started
Database Drivers
Schema Integrations
Seed Generators
Utilities and Testing
The following files were used as context for generating this wiki page:
Schema Serialization is the architectural backbone of Drizzle Kit, providing a deterministic mechanism to capture, persist, and compare database schema states. Its primary purpose is to enable "Database Diffing"—the ability to calculate exactly what DDL statements are required to transform one database schema state into another.
By serializing database schemas into rigid JSON structures, the system abstracts away the complexities of disparate database engines (PostgreSQL, MySQL, SQLite, etc.) into a unified, versioned format. This process solves the fundamental problem of maintaining consistency between code-defined schemas and actual database states, ensuring that migrations are generated predictably and safely.
The subsystem functions as a pipeline: it first introspects the live database (or the ORM schema configuration), converts that into a versioned internal schema format defined by Zod types, and finally, during migration generation, applies a diffing algorithm. This diffing step compares two serialized states, resolves renames, and produces an ordered sequence of migration statements that align the destination with the source, all while preserving data integrity and handling database-specific constraints.
The schema serialization process follows a multi-stage lifecycle designed to ensure data consistency during transitions. Serialization begins with the extraction of definitions—tables, columns, indexes, and constraints—from the database configuration. These raw definitions are transformed into internal objects, which are then mapped or squashed for persistence.
The "squashing" process is critical; it converts complex, nested database objects into flattened, serialized string formats (for instance, encoding index definitions or composite primary keys into specific string delimiters). This normalization allows for simpler diffing algorithms, as the system can compare strings instead of deeply recursive object trees.
Sources: drizzle-kit/src/serializer/pgSchema.ts:758-868, drizzle-kit/src/serializer/gelSchema.ts:505-615
To accommodate evolution, the system employs versioned schema definitions. Each major version defines the shape of the stored JSON using Zod. This allows Drizzle Kit to read older definitions while evolving the internal model without breaking compatibility with existing migration folders.
Sources: drizzle-kit/src/serializer/pgSchema.ts:437-509, drizzle-kit/src/serializer/gelSchema.ts:272-272
The serialization engine utilizes specific helper methods defined inside schema definitions to handle flattening operations. These helper functions contain the "load-bearing" methods for the system, converting complex objects (like indexes or foreign keys) into flattened strings, which are the data-transfer format between the serializable JSON and the diffing logic.
For instance, an index is converted into a string delimited by semicolons and double hyphens (e.g., parsing the index properties and columns to join them with ,, and --). This flattened string is deterministic, allowing the snapshotsDiffer module to perform direct string equality checks to determine if an object has changed.
Important
The squash format is engine-specific and highly sensitive to delimiters. Adding or changing a delimiter in these serialization helpers without updating the corresponding parser and unsquashing logic will result in corrupted states and failed migrations.
Sources: drizzle-kit/src/serializer/pgSchema.ts:551-756, drizzle-kit/src/serializer/gelSchema.ts:298-503
The snapshotsDiffer.ts component is the engine room for calculating migration statements. It takes two serializations (the "old" and "new") and computes a list of required JSON statements. The process is inherently ordered: it first resolves global schema changes (like adding or renaming a schema), then table additions, column updates, and finally, dependent constraints like indexes and foreign keys.
applyPgSnapshotsDiffdiffSchemasOrTables(): Calculates the basic set difference between the old and new states.schemasResolver()/enumsResolver(): User-provided resolution hooks are called to handle renaming/moving logic, which might otherwise be ambiguous.mapEntries(): Updates the cached state to align names/schemas according to the resolved renames.diffColumns()/diffPolicies(): Calculates granular diffs for columns and policies.prepare...() functions: Finally, the system dispatches the differences to jsonStatements.ts generators to produce the final JsonStatement[] list.Sources: drizzle-kit/src/snapshotsDiffer.ts:603-1245
When a schema structure changes (e.g., a table is renamed), simply observing the "added" and "deleted" sets is insufficient, as it leads to "drop-and-create" rather than a "rename." The interfaces, such as ResolverInput and ResolverOutput, exist to allow external logic to clarify the intent.
The system requires these inputs to resolve "renames" vs "newly created/deleted" entities.
Sources: drizzle-kit/src/snapshotsDiffer.ts:421-505
Not all diffs are strictly necessary. The engine includes a filtering pipeline at the end of the apply functions to remove redundant or conflicting SQL operations. For instance, if an operation drops a NOT NULL constraint and another operation modifies the same column's identity, these are analyzed for logical collisions.
// Example of a filtering guard in snapshotsDiffer.ts
const filteredJsonStatements = jsonStatements.filter((st) => {
if (st.type === 'alter_table_alter_column_drop_notnull') {
if (jsonStatements.find((it) => it.type === 'alter_table_alter_column_drop_identity' ...)) {
return false;
}
}
return true;
});Sources: drizzle-kit/src/snapshotsDiffer.ts:2025-2051
Warning
Statement order is non-negotiable. Indexes must often be dropped before altering columns and recreated afterward. The apply methods manually append these statement arrays in a precise, hard-coded order at the end of the migration generation phase to respect database dependency constraints.
Sources: drizzle-kit/src/snapshotsDiffer.ts:1985-2022