Skip to main content
doc0blade47/drizzle-ormdocumentation home
Sign in

Migration Toolkit Schema

Last updated Oct 12, 202690% grounded
Relevant source files

The following files were used as context for generating this wiki page:

Overview

The Migration Toolkit Schema subsystem forms the structural bridge between user-defined TypeScript database layouts in Drizzle ORM and physical database state. It operates across multiple target dialects—PostgreSQL, MySQL, SQLite (including LibSQL/Turso), SingleStore, and Gel—by translating code definitions and live database introspections into versioned, normalized JSON snapshots and migration journals.

Sources: drizzle-kit/src/api.ts:64-92

At its core, this architecture decouples schema representation from specific database drivers. By validating schema objects against Zod structural specifications, drizzle-kit can diff successive snapshots, compute granular change sets (jsonStatements), filter out non-breaking or pseudo-changes (such as automatic type promotions), and safely apply structural mutations or generate migration files.

Sources: drizzle-kit/src/serializer/index.ts:12-56

Sources: drizzle-kit/src/snapshotsDiffer.ts:1-16


Schema Diffing and SQL Generation

The schema diffing subsystem compares a previous schema snapshot (json1) against a current schema snapshot (json2) to produce an intermediate array of semantic JSON statement descriptors. These descriptors are subsequently lowered into concrete SQL queries by the SQL generator or filtered and executed by the push utilities.

Sources: drizzle-kit/src/snapshotsDiffer.ts:98-123

When generating migrations or pushing schema updates, applyPgSnapshotsDiff, applyMysqlSnapshotsDiff, and related diffing functions inspect tables, columns, constraints, foreign keys, and indexes. For dialects like SQLite and LibSQL where table alterations are restricted, the differ identifies situations requiring table recreation (recreate_table) via temporary tables and data copying (_moveDataStatements).

Sources: drizzle-kit/src/api.ts:159-186

Sources: drizzle-kit/src/cli/commands/libSqlPushUtils.ts:28-111

The table below outlines common statement types generated during the diffing process and their structural targets across dialects:

Statement TypeDescriptionTarget Dialects
create_tableProvisions a new database table with columns and constraintsPostgreSQL, MySQL, SingleStore, SQLite
drop_tableRemoves a table and verifies dependent row countsAll Dialects
alter_table_add_columnAppends a column definition to an existing tableAll Dialects
alter_table_drop_columnDrops a column after checking for item countsAll Dialects
recreate_tableRebuilds SQLite/LibSQL tables via temporary __new_ tablesSQLite, LibSQL
create_type_enumCreates native enumeration typesPostgreSQL

Sources: drizzle-kit/src/jsonStatements.ts:45-111, drizzle-kit/src/cli/commands/libSqlPushUtils.ts:32-64


Schema Push Mechanics

Schema push operations (pushSchema, mysqlPush, pgPush, sqlitePush, libSQLPush) synchronize a live database instance with the TypeScript schema without generating explicit migration files. They achieve this by introspecting the live database catalog into a normalized schema structure, serializing the target TypeScript schema, running the snapshot differ, filtering pseudo-changes, and prompting users when destructive operations are detected.

Sources: drizzle-kit/src/api.ts:125-188

Filtering mechanisms prevent redundant updates, such as boolean default variations or automatic promotions between bigint unsigned and serial column types in MySQL and SingleStore. Furthermore, safety validation layers inspect live row counts before executing destructive statements such as dropping tables or columns, adding non-null columns without defaults, or modifying primary keys.

Sources: drizzle-kit/src/cli/commands/mysqlPushUtils.ts:10-105

Warning

When pushing changes to SQLite or LibSQL databases, adding a NOT NULL column without a default value to a populated table triggers an automatic table truncation or forces deletion of rows to prevent constraint violations.

Sources: drizzle-kit/src/cli/commands/libSqlPushUtils.ts:173-196

The following example demonstrates how programmatic schema pushing is invoked using pushSchema for PostgreSQL:

import { pushSchema } from 'drizzle-kit/api';
import { drizzle } from 'drizzle-orm/node-postgres';
import * as schema from './schema';
 
const dbInstance = drizzle(process.env.DATABASE_URL!);
 
async function syncSchema() {
  const result = await pushSchema(schema, dbInstance, ['public'], ['__drizzle_migrations']);
  
  if (result.hasDataLoss) {
    console.warn('Warnings:', result.warnings);
  }
  
  await result.apply();
  console.log('Schema pushed successfully.');
}

Sources: drizzle-kit/src/api.ts:125-188


Schema Snapshot Serializer

The snapshot serializer transforms AST exports and database reflection results into versioned, structured Zod-validated JSON documents. Each dialect maintains strict validation schemas (e.g., pgSchemaInternal, schemaInternal for SQLite and SingleStore, gelSchemaExternal) capturing tables, columns, indexes, foreign keys, composite primary keys, check constraints, unique constraints, and policies.

Sources: drizzle-kit/src/serializer/pgSchema.ts:365-438

Versioning ensures backward compatibility across migration toolkit upgrades. For example, PostgreSQL snapshots have evolved through versions 3 through 7, introducing proper schema namespace support (schema.table notation), sequence metadata tracking, and internal kit state tracking (kitInternals).

Sources: drizzle-kit/src/serializer/sqliteSchema.ts:82-132, drizzle-kit/src/serializer/singlestoreSchema.ts:89-102, drizzle-kit/src/serializer/gelSchema.ts:216-222

Was this page helpful?