RepoPilot

How does Drizzle handle schema migrations?

About drizzle-team/drizzle-orm · 2 messages · last activity 7/26/2026

Question

How does Drizzle handle schema migrations?

RepoPilot

Drizzle's migration story is split between the drizzle-orm runtime library and the drizzle-kit CLI companion, and it's evolved noticeably over the project's history:

Runtime migration execution (drizzle-orm) Early on, migration functionality was pulled out into its own dedicated import path rather than being bundled into the main driver import. For example:

  • PostgreSQL: import { migrate } from 'drizzle-orm-pg/node/migrate' [changelogs/drizzle-orm-pg/0.14.0.md:L1-L9]
  • SQLite: import { migrate } from 'drizzle-orm-sqlite/better-sqlite3/migrate' [changelogs/drizzle-orm-sqlite/0.14.1.md:L1-L9]

This same release also replaced the old connector pattern (await new PgConnector(client).connect() / new SQLiteConnector(client).connect()) with a simpler drizzle(client) call [changelogs/drizzle-orm-pg/0.14.0.md:L1-L9] [changelogs/drizzle-orm-sqlite/0.14.1.md:L1-L9].

Schema generation and pushing (drizzle-kit) Drizzle Kit is the CLI tool responsible for generating SQL migration files from your TypeScript schema or applying schema changes directly to the database — described in the README as a "hassle-free migrations" companion [README.md:L29-L35].

Key behaviors:

  • Generate: Drizzle Kit diffs your Drizzle schema (tables, views, materialized views, check constraints, etc.) against the database/previous migrations and emits SQL DDL. For example, a pgTable with a check() constraint plus a pgView and pgMaterializedView generates CREATE TABLE, CREATE VIEW, and CREATE MATERIALIZED VIEW statements accordingly [changelogs/drizzle-kit/0.26.0.md:L50-L107]. Materialized views are PostgreSQL-only; regular views work across all dialects [changelogs/drizzle-kit/0.26.0.md:L98-L100].
  • Push: Applies schema changes directly to the database without generating migration files, but has documented limitations — e.g., changing a view's SQL definition via push alone requires manually commenting the view out, pushing, then restoring it with the new definition and pushing again [changelogs/drizzle-kit/0.26.0.md:L100-L107].

Behavioral changes over time A significant shift happened in drizzle-kit 0.30.0: the PostgreSQL dialect stopped emitting IF NOT EXISTS, $DO, and similar guard statements in migrations, aligning it with how other dialects behave. Previously these guards could silently swallow errors when an object already existed and should have failed. This is explicitly called out as the first step toward larger planned upgrades: commutative migrations, a revised migration folder structure, better collaboration support, improved Xata migration support, and CockroachDB compatibility [changelogs/drizzle-kit/0.30.0.md:L1-L7].

Naming/casing strategy Drizzle Kit 0.25.0 introduced a casing config option so schema definitions can use camelCase in TypeScript while automatically mapping to snake_case in the database, both at the drizzle() connection level (casing: 'snake_case') and in drizzle.config.ts for migration generation, ensuring consistency between runtime queries and generated migrations [changelogs/drizzle-kit/0.25.0.md:L146-L180].

Dialect expansion As of drizzle-kit 0.30.5, a new Gel dialect was added, but with a notably different migration workflow: Drizzle does not support generate, migrate, or push for Gel. Instead, the Gel CLI itself manages schema and migrations, and drizzle-kit is used only via drizzle-kit pull to reverse-engineer a Drizzle schema from the Gel database for use in drizzle-orm queries [changelogs/drizzle-kit/0.30.5.md:L3-L30].

Schema namespacing For PostgreSQL specifically, drizzle-orm-pg 0.15.1 added support for PostgreSQL schemas via pgSchema(...). Tables in the default `

Want to ask your own question?

Open chat for drizzle-team/drizzle-orm

Public Q&A. Generated by RepoPilot from the actual source of drizzle-team/drizzle-orm. AI answers can be incomplete or stale — verify before relying on them.