What changes
In drizzle-kit 0.x (legacy), the SQL files sat side by side and every migration was registered in meta/_journal.json, next to one snapshot per migration.
drizzle-kit 0.x (legacy)
drizzle-kit v1
drizzle/├─ 0000_brave_wolverine.sql├─ 0001_silly_hulk.sql└─ meta/ ├─ _journal.json ├─ 0000_snapshot.json └─ 0001_snapshot.jsondrizzle/├─ 20250220153045_brave_wolverine/│ ├─ migration.sql│ └─ snapshot.json└─ 20250221091210_silly_hulk/ ├─ migration.sql └─ snapshot.jsonBuilt for branches
The journal was the one file every migration touched. Two branches that each generated a migration both edited it, so merging them meant a Git conflict on _journal.json. With one folder per migration, there is no shared file to conflict on.
v1 also applies every missing migration, not just the ones newer than the last applied one. A migration that lands from a branch created earlier no longer gets skipped.
Commutativity checks
Two migrations commute when running them in either order gives the same database, like a + b = b + a.
Say Alice and Bob branch from main and each generate a migration. After both merge, Alice’s database ran hers first, Bob’s ran his first, and production runs them in whatever order it gets them. If the order changes the result, the databases drift apart, or one migration fails on one of them.
- AALTER TABLE users ADD avatar text
- BALTER TABLE posts ADD slug text
- idserial
- nametext
- idserial
- titletext
- BALTER TABLE posts ADD slug text
- AALTER TABLE users ADD avatar text
- idserial
- nametext
- idserial
- titletext
Step 1 of 4. Both branches start from the same schema.
drizzle-kit check (also run by drizzle-kit generate and drizzle-kit migrate) flags overlapping changes, where the order matters.drizzle-kit checks this from your migration folders, without a database:
- It rebuilds the history. Each
snapshot.jsonstores its ownidandprevIds, the snapshot it was generated from. Two migrations with the same parent are two branches. - It lists what each branch changes. For each fork, it diffs the parent snapshot against the last snapshot of each branch, which gives each branch’s DDL statements.
- It compares what they touch. Each statement touches objects: a column, its table, its schema. Each kind of statement also names the kinds it cannot share an object with.
DROP TABLE postsclashes with any column change onposts.ADD COLUMN users.avataronly clashes with another change tousers.avatar, so a newusers.biois fine. - It reports or joins. A clash is reported with both migration folders and the two statements. Without one, the next
drizzle-kit generatestarts from the parent plus both branches, and its snapshot lists both branches as parents. The history is one line again.
┌─ A: ADD COLUMN users.avatar ─┐parent ────┤ ├── next generate (prevIds: A, B) └─ B: ADD COLUMN posts.slug ───┘What to do with each result:
- Independent changes: one branch adds
users.avatar, the other addsposts.slug. Any order gives the same result, so the branches merge. - Same table, other columns: one branch adds
users.avatar, the other addsusers.bio. drizzle-kit compares column by column, so this merges too. The new columns may end up in a different order in each database. That is fine, because Drizzle names every column in the queries it builds. On SQLite and Turso, changing a column’s type, default orNOT NULLrebuilds the whole table, so that change clashes with any other column change on the same table. - Overlapping changes: one branch drops the
poststable, the other addsposts.slug. Order matters, like a Git conflict. Delete your migration (only if it has not run anywhere yet) and regenerate it so it builds on your teammate’s.
Run the check
drizzle-kit check runs it on its own, without generating or applying anything. Run it in CI on every pull request. It exits with an error when it finds a clash, before anyone runs the migrations.
npx drizzle-kit checkpnpm drizzle-kit checkyarn drizzle-kit checkbunx drizzle-kit checkIt also validates every snapshot.json first. A snapshot still in the 0.x format fails with a hint to run drizzle-kit up. Add --output json for a machine-readable result.
The same check runs in drizzle-kit generate and drizzle-kit migrate, not in migrate() from your app. All three commands accept --ignore-conflicts to skip it. If you want the background, the design discussion is in Commutative Migrations (GitHub discussion, opens in a new tab).
Upgrade in 3 steps
-
Install
1.0.0-rc.4exactly. Do not use@rc, it will install rc.5 as soon as it ships. Caret ranges like^1.0.0-rc.4already resolve torc.5-<hash>snapshot builds.npm i -E drizzle-orm@1.0.0-rc.4npm i -D -E drizzle-kit@1.0.0-rc.4pnpm add -E drizzle-orm@1.0.0-rc.4pnpm add -D -E drizzle-kit@1.0.0-rc.4yarn add -E drizzle-orm@1.0.0-rc.4yarn add -D -E drizzle-kit@1.0.0-rc.4bun add -E drizzle-orm@1.0.0-rc.4bun add -d -E drizzle-kit@1.0.0-rc.4In a monorepo, check that both packages resolve from the same
node_modules(npm ls drizzle-orm drizzle-kit). drizzle-kit loads drizzle-orm at runtime without declaring it, so a nested drizzle-orm fails withCannot find module 'drizzle-orm/_relations'(drizzle-orm#5573 (GitHub issue, opens in a new tab)). -
Commit, then convert your migrations folder. This step is required because
migrate()in your app throws whilemeta/_journal.jsonexists.updeletes the old.sqlfiles and themeta/folder, so Git is your only way back.npx drizzle-kit uppnpm drizzle-kit upyarn drizzle-kit upbunx drizzle-kit upupreads yourdrizzle.config.ts, or takes--config,--dialectand--outflags.import { defineConfig } from "drizzle-kit";export default defineConfig({dialect: "postgresql",schema: "./src/db/schema.ts",out: "./drizzle",});Your app keeps applying migrations from the same folder:
import { drizzle } from "drizzle-orm/node-postgres";import { migrate } from "drizzle-orm/node-postgres/migrator";const db = drizzle(process.env.DATABASE_URL!);await migrate(db, { migrationsFolder: "./drizzle" });Then run
drizzle-kit check(expect no conflict) anddrizzle-kit generate(expect no new migration). -
Update your code and scripts. Start with Changes your code needs, then read the upgrade guide (Drizzle docs, opens in a new tab) and the v0 to v1 changes (Drizzle docs, opens in a new tab).
Ready to test your knowledge?
Changes your code needs
Pass the client as { client }
drizzle(client) and drizzle(client, opts) still work in 0.45. v1 only takes the object form, drizzle({ client }). The v0 to v1 changes do not list this yet.
drizzle-orm 0.45
drizzle-orm v1
import postgres from "postgres";import { drizzle } from "drizzle-orm/postgres-js";
const db = drizzle(postgres(process.env.DATABASE_URL!));import postgres from "postgres";import { drizzle } from "drizzle-orm/postgres-js";
const db = drizzle({ client: postgres(process.env.DATABASE_URL!) });TypeScript flags it, but the runtime does not throw. With postgres-js, a client passed positionally is ignored, and drizzle opens a new connection from the PG* environment variables or localhost. Check plain JS files, scripts outside your tsconfig, and anything cast to any. drizzle(url) and drizzle({ connection }) still work.
Remove the schema option
drizzle() no longer takes schema because relational queries v1 are gone. If you never call db.query.*, delete the option. Otherwise, move to defineRelations() with the relations v1 to v2 guide (Drizzle docs, opens in a new tab).
Check your package scripts and CI
drizzle-kit dropis gone. It prints a notice and exits 0, so a script that calls it succeeds without doing anything. Delete a migration’s folder instead.push --strictis gone.- Anything that reads
_journal.json,meta/orNNNN_*.sqlpaths breaks. pushandpullnow manage every schema, not onlypublic. SetschemaFilter(Drizzle docs, opens in a new tab) to the schemas your tables use.
Not required yet
getTableColumnsstill works in rc.4. It is marked@deprecatedin favor ofgetColumns.drizzle-zod,drizzle-valibot,drizzle-typeboxanddrizzle-arktypestill work, but get no updates. Their replacements aredrizzle-orm/zod,drizzle-orm/valibot,drizzle-orm/typeboxanddrizzle-orm/arktype.
Before you run migrations
The upgrade changes files only. The first v1 migrate() (or drizzle-kit migrate) changes your database:
- It alters the migrations table (
__drizzle_migrationsby default). It addsnameandapplied_at, then backfillsnamefor each applied migration (docs (Drizzle docs, opens in a new tab)). - It throws if the database holds a migration with no local folder. Compare the row count of the migrations table with your migration folders first.
- It applies every local migration missing from the database, even one older than the last applied. 0.45 skips those (docs (Drizzle docs, opens in a new tab)).
Back up the database first, and try it on a local copy or a staging database before production. Deploy the code and the converted folder together, since the 0.x migrator cannot read the new layout and the v1 migrator refuses a folder that still has meta/_journal.json.
Let an agent do it
This prompt upgrades a project from 0.x to 1.0.0-rc.4 with a coding agent. It is for rc.4 only. A new one will come with rc.5, and another with the final v1.
It follows a few hard rules:
- No database. The agent never runs
migrate,push,pull,studioordrop, or any script that connects to a database. Applying migrations stays your job. - Clean tree first. It stops if
git statusis not clean, and runsuponly then. - Nothing committed. Every change stays in your working tree for review, with 3 suggested commits and an undo command.
- Required changes only. It changes code only when the installed rc.4 proves it necessary (a type error, a throw, a silent runtime change), and reports the rest with a doc link and the
node_modulesline that proves it.
We ran it with Claude Code on a production monorepo on the latest stable (drizzle-orm 0.45, drizzle-kit 0.31, 42 Postgres migrations, postgres-js). Every migration.sql stayed byte-identical, check and generate came back clean, and typecheck had no new errors.
# Upgrade this project from Drizzle 0.x to 1.0.0-rc.4
You are upgrading this repository from `drizzle-orm` 0.x / `drizzle-kit` 0.x to `1.0.0-rc.4`. Work through the phases below in order. Each phase ends with a check; do not start the next phase until it passes.
## Hard rules
These override anything else, including Drizzle's own agent skills.
1. **Never touch a database.** Do not run `drizzle-kit migrate`, `push`, `pull`, `studio` or `drop`, any project script that applies migrations or connects to a database (deploy, seed, `migrate()` scripts), or any app or test command that needs a live database. Applying migrations is the user's job. This holds even to check a command's behavior or exit code: read its source in `node_modules` instead of running it.2. **Never read `.env*` files** or print connection strings.3. **Run `drizzle-kit up` only if the working tree was clean in Phase 1.** Since then, the only changes may be your own. Git is the only way back: `up` deletes the old `.sql` files and the `meta/` folder. To undo it, run `git restore --source=HEAD --staged --worktree -- <out> && git clean -fd -- <out>`.4. **Pin exact versions.** Install `1.0.0-rc.4` exactly (no `@rc`, no `^`). `@rc` and `^1.0.0-rc.4` later resolve to `rc.5-<hash>` snapshot builds.5. **Install nothing else from the network.** Besides the two Drizzle packages (and the stable `drizzle-kit@0.31` in Phase 3 if needed), do not install or download anything. Do not run `drizzle-kit skills`, which downloads and runs `skills@latest`. `drizzle-kit skills version` is local and fine.6. **Do not paper over errors.** No `@ts-ignore`, `as any`, or skipped tests to make the upgrade pass.7. **Stay in scope.** Do not fix unrelated pre-existing failures; record them.8. **Do not commit, stash, or switch branches.** Leave every change uncommitted, so the user can review the diff and commit it themselves.9. **Source every claim, never guess.** Each item you report, in the preflight or the final report, gets: - **Doc:** the link from the Reference section, or "not documented"; - **Evidence:** a `node_modules` `file:line`, once rc.4 is installed.
Do not write "probably", "likely" or "I think". State what the doc says. If you could not check something, write "not verified" and say why.
Use the project's package manager (detect it from the lockfile or the `packageManager` field) and run Drizzle binaries through it: `npx drizzle-kit`, `pnpm exec drizzle-kit`, `yarn drizzle-kit`, or `bunx drizzle-kit`. Always pass `--output json` to drizzle-kit commands and read the JSON.
## Reference: what changed in v1
Each item below says what changed in `1.0.0-rc.4` and links the official doc that explains it. Use these links in the preflight report, and again in the final report. Phase 5 checks each one against the installed code.
- **Driver constructor.** Only a positional driver *client* is affected. - `drizzle(url)`, `drizzle(url, opts)` and `drizzle({ connection })` still work: leave them as they are. - `drizzle(client)` and `drizzle(client, opts)`, where `client` is a driver instance (a `postgres()` client, a `pg` Pool, and so on), were valid in 0.x. They no longer type-check in rc.4: the object form is `drizzle({ client, ...opts })`. - With postgres-js, a client passed positionally is silently ignored at runtime, and drizzle opens a new connection from `PG*` env variables or `localhost` (`postgres-js/driver.js`). That makes every such call site Required, including plain JS, scripts and anything cast to `any`. Check your own driver's `driver.js`. - Doc: the positional client was deprecated in 0.35.0 and removed on purpose in `1.0.0-beta.11`, but the removal is not listed in the v0 to v1 changes. The connection pages show the client form, for example https://orm.drizzle.team/docs/get-started-postgresql#postgresjs ("If you need to provide your existing driver"). Cite the code as the main evidence.- **`schema` option and relational queries.** RQB v1 is removed from the types: `drizzle()` has no `schema` option, and `defineRelations()` passed as `relations` replaces `relations()`. - If the code never calls `db.query.*`, removing `schema` (and the now-unused import) is the whole change. - If it does, migrate the relations and queries with https://orm.drizzle.team/docs/relations-v1-v2, and list every changed query in the report for the user to test. - Doc: https://orm.drizzle.team/docs/v0-v1-changes#relational-queries-v1-removed- **`getTableColumns`:** documented as deprecated and replaced by `getColumns` (same arguments). It is still exported in rc.4, marked `@deprecated`. Doc: https://orm.drizzle.team/docs/v0-v1-changes#gettablecolumns-deprecation- **`casing` in `drizzle()`:** replaced by `snakeCase.table` / `camelCase.table` from the dialect core. Check whether the option is still accepted. Doc: https://orm.drizzle.team/docs/v0-v1-changes#new-casing-api- **Validators:** `drizzle-zod`, `drizzle-valibot`, `drizzle-typebox` and `drizzle-arktype` still work but get no updates. - Replacements: `drizzle-orm/zod`, `drizzle-orm/valibot`, `drizzle-orm/typebox` (or `drizzle-orm/typebox-legacy`) and `drizzle-orm/arktype`. - Report them; do not switch. - Doc: https://orm.drizzle.team/docs/v0-v1-changes#validator-packages-consolidated-into-drizzle-orm- **Schema API.** After any Required schema edit, `generate --output json` must still return `no_changes`. - `.array().array()` becomes `.array('[][]')`. Doc: https://orm.drizzle.team/docs/v0-v1-changes#array-is-no-longer-chainable - `.enableRLS()` becomes `pgTable.withRLS(...)`. Doc: https://orm.drizzle.team/docs/v0-v1-changes#enablerls-deprecated - `.generatedAlwaysAs('expr')` with a plain string becomes `` sql`expr` ``. Doc: https://orm.drizzle.team/docs/v0-v1-changes#generatedalwaysas-only-accepts-sql- **Scripts and CI (report only):** - `drizzle-kit drop` is removed (https://orm.drizzle.team/docs/v0-v1-changes#new-migration-folder-structure-v3). Its exit code is not documented. In rc.4 the command prints a deprecation notice and exits 0, so the script silently does nothing. Confirm this by reading `drizzle-kit/bin.cjs` (search for `To drop a migration`), never by running `drop`. Drop a migration by deleting its folder. - A script named like a check that runs `drizzle-kit up` should run `drizzle-kit check`, which is the v1 check command (https://orm.drizzle.team/docs/drizzle-kit-check). - `push --strict` is gone (https://orm.drizzle.team/docs/v0-v1-changes#drizzle-kit-push---strict-deprecation). - Anything that reads `_journal.json` or `meta/` breaks (https://orm.drizzle.team/docs/v0-v1-changes#new-migration-folder-structure-v3).- **`schemaFilter` (report only):** `push` and `pull` now manage all schemas by default, not only `public`. If you suggest a value, list every schema the project's schema files use: `public` if any table lives there, plus each `pgSchema(...)` / `mysqlSchema(...)` name. - Doc: https://orm.drizzle.team/docs/v0-v1-changes#schemafilter-default-behavior-changed - Doc: https://orm.drizzle.team/docs/drizzle-config-file#schemafilter- **Custom type parsers (report only):** v1 adds driver codecs that change how dates, JSON and bigint values are mapped. - Check the `mode` of the affected columns and the matching entry in `node_modules/drizzle-orm/<driver>/codecs.js` (for example, `timestamp:string` has no normalizer, but `timestamp` does). - Say "untested" rather than predict a failure you did not reproduce. - Doc: https://orm.drizzle.team/docs/codecs (and #how-codecs-work-in-customtype for `customType()`).
## Phase 1: Preflight (read only)
1. Run `git status --porcelain` (untracked files count). **If it prints anything, stop.** Tell the user to commit or stash their changes, then run this prompt again. Do not stash or commit their work yourself.2. Find every package that declares `drizzle-orm` or `drizzle-kit`. Note their versions and any other Drizzle packages: `drizzle-zod`, `drizzle-valibot`, `drizzle-typebox`, `drizzle-arktype`, `drizzle-seed`, `eslint-plugin-drizzle`.3. Find every drizzle-kit config (`drizzle.config.*`) and its `dialect`, `schema` and `out`. If there is no config, find the migrations folder (a folder with `meta/_journal.json`) and the dialect from code.4. For each `out` folder, read `"version"` in the first `meta/*_snapshot.json`. Read it as JSON: some snapshots put `"id"` before `"version"`.5. Inventory the candidate sites (Phase 5 decides which ones change). Search source, scripts, CI and Docker files, `.js` included: - every `drizzle(` call and what it receives; - relational queries: `db.query.`, `relations(` from `drizzle-orm`, and the `schema` option of `drizzle()`; - `getTableColumns`, `casing:`, `.array().array()`, `.enableRLS()`, `.generatedAlwaysAs('` with a plain string; - imports from `drizzle-zod`, `drizzle-valibot`, `drizzle-typebox` or `drizzle-arktype`; - package scripts and CI steps that call `drizzle-kit drop`, `drizzle-kit up`, `push --strict`, or that reference `_journal.json`, `meta/` or `NNNN_*.sql` paths; - custom driver type parsers or serializers (for example `client.options.parsers` with postgres-js, or `types.setTypeParser` with node-postgres).6. Record a baseline by running the project's existing typecheck, lint, unit test and build commands, skipping any that need a database. Save the exact pass/fail state and error counts; Phase 6 compares against it.7. Check whether this is a monorepo, and which `node_modules` resolves `drizzle-orm` and `drizzle-kit`.
## Phase 2: Confirmation (stop and wait for the user)
Show the user a short preflight report:
- the packages, configs, migration folders and snapshot versions found;- the candidate code sites from the inventory: for each one, the files, what the Reference says about it, and its doc link. Phase 5 confirms the classification against the installed rc.4;- the baseline results;- the plan: install the RC, convert the migrations folder, make only the required code changes, report the rest, and leave every change uncommitted for the user to review.
Then show this notice and ask the user to confirm before you continue:
> This upgrade changes code and migration files only. The first time your app or CI runs the v1 migrator against a database, it alters the migrations table (`__drizzle_migrations` by default). It adds `name` and `applied_at` columns and backfills them (https://orm.drizzle.team/docs/v0-v1-changes#updates-to-the-migration-table). Applying that is your responsibility, not the agent's. Before you do:> - **Back up the database** (for example `pg_dump`, `mysqldump`, or a copy of the SQLite file).> - **Production users:** try it on a local copy or a staging database first. Never go straight to production.
**Do not continue until the user confirms.** Any clear go-ahead counts ("yes", "ok", "go", "implement"); do not ask them to rephrase or restate the notice. If they decline, stop.
## Phase 3: Old snapshots (only if a snapshot version is below 7)
The RC's `up` converts v5/v6 snapshots into files it later rejects as malformed (the next `check` fails with `snapshot.json data is malformed`). Fix them first with the latest stable kit, while the old folder layout is still in place:
1. Run `drizzle-kit@0.31 up` for each config. If the installed kit is already `0.31.x`, use the installed binary; otherwise run the stable kit once without saving it.2. Check that every `meta/*_snapshot.json` is now version 7 and that the SQL files are unchanged (`git diff --stat` shows only `meta/` files).
## Phase 4: Install and convert the migrations folder
1. In each package that declares them, install `drizzle-orm@1.0.0-rc.4` as a dependency and `drizzle-kit@1.0.0-rc.4` as a devDependency, both pinned exactly (`--save-exact`, `--exact`, or `-E`). Run the install from the package that declares them (or with the workspace flag); do not add Drizzle to a monorepo root that did not have it.2. Check that both resolve to exactly `1.0.0-rc.4`, from the same `node_modules`. drizzle-kit loads drizzle-orm at runtime without declaring it. If npm nests drizzle-orm under the app (for example because of an optional-peer conflict on `@sinclair/typebox`), drizzle-kit fails with `Cannot find module 'drizzle-orm/_relations'`. Report that and propose a fix; do not force-install.3. Check that `git status --porcelain` lists only package manifests, the lockfile and, after Phase 3, `meta/` snapshots. **Nothing inside `<out>` other than `meta/` may have changed before `up`.**4. Read Drizzle's bundled agent skills, now on disk at `node_modules/drizzle-kit/skills/*/SKILL.md`: `drizzle`, `drizzle-migrations`, `drizzle-generate`, `drizzle-responses-and-errors`, `drizzle-hints`. Follow them for reading drizzle-kit JSON output and hints. The hard rules above win where they disagree; `drizzle-push` and anything that applies migrations stay off limits. Some text in those skills still describes the 0.x `meta/_journal.json` layout; after `up`, trust the folder you see.5. For each config, run `drizzle-kit up --output json` (add `--config <path>` when there are several). It should return `"status":"ok"` and list the upgraded snapshots.6. Verify the conversion for each `out` folder: - the `meta/` folder is gone, and there is one `<14-digit UTC timestamp>_<name>/` folder per old `.sql` file, each holding `migration.sql` and `snapshot.json`; - each `migration.sql` is byte-identical to its old `.sql`. Run this from the package folder, where `<out>` is the `out` path relative to it:
```sh node -e ' const { execSync } = require("child_process"), fs = require("fs"), path = require("path"); const [out, ref = "HEAD"] = process.argv.slice(1); const journal = JSON.parse(execSync(`git show ${ref}:./${out}/meta/_journal.json`)); const dirs = fs.readdirSync(out).filter((d) => fs.existsSync(path.join(out, d, "migration.sql"))).sort(); let bad = 0; journal.entries.forEach((e, i) => { const before = execSync(`git show ${ref}:./${out}/${e.tag}.sql`); const after = dirs[i] && fs.readFileSync(path.join(out, dirs[i], "migration.sql")); if (!after || !before.equals(after)) { bad++; console.log("MISMATCH", e.tag, "->", dirs[i]); } }); console.log(`${journal.entries.length} journal entries, ${dirs.length} folders, ${bad} mismatches`); process.exit(bad || journal.entries.length !== dirs.length ? 1 : 0); ' <out> ```
- running `drizzle-kit up --output json` again returns an empty `upgraded` list; - `drizzle-kit check --output json` returns `"status":"ok"`. A commutativity conflict here means two migrations in the history touch the same objects; report it, do not resolve it; - `drizzle-kit generate --output json` returns `"status":"no_changes"`. If it writes a new migration folder instead, the schema and the snapshots disagree: delete that new folder, stop, and show the user the SQL it contained.
## Phase 5: Code changes (required only)
**The installed code is the source of truth, not this prompt and not the docs.** For each site in the Phase 1 inventory, look up the API in the installed packages:
- `node_modules/drizzle-orm`: `.d.ts` for types and `@deprecated` tags, `.js` for runtime behavior;- `node_modules/drizzle-kit`: `--help` and `bin.cjs`.
Then classify the site:
| Class | Proof in the installed code | Action ||---|---|---|| Required | It no longer type-checks, it throws, or it silently behaves differently at runtime (an ignored option, another client, another value) | Change it, with the smallest edit || Deprecated | It is still exported and works, but is marked `@deprecated` or prints a warning | Do not change it; report it with the replacement || Unchanged | It works as before | Nothing |
For every Required or Deprecated item, keep the evidence (`file:line` in `node_modules`) for the report. If the installed code disagrees with the Reference section, follow the code and report the mismatch.
**Package scripts, CI and Docker files are the user's workflow: report them, never edit them.** Say what the installed kit now does for each one and suggest a replacement.
Use the **Reference** section above for what to look for and the doc link of each item. Verify each one against the installed code.
## Phase 6: Validate
1. Rerun the Phase 1 baseline commands and compare. The upgrade must not add a failure; pre-existing failures stay out of scope.2. Run `drizzle-kit check --output json` and `drizzle-kit generate --output json` once more (`ok`, `no_changes`).3. Optional offline smoke test, no database needed. In a temporary script, build `drizzle({ client })` with a client pointed at an unreachable host. Then call `.toSQL()` on one select over one of your tables, and delete the script.4. `git status --porcelain` lists only expected changes: package manifests, the lockfile, `<out>`, and the files listed under required code changes. No temporary script or stray migration folder is left behind.
## Final report
Reply with these sections, short and scannable.
**Source every item.** Each changed, reported or flagged item gets:- **Why:** one line, in plain words;- **Doc:** the official link from the Reference section (or the most specific page you found). Write "not documented" when no doc covers it;- **Evidence:** the `node_modules` file and line that proves it.
A reader who did not follow the run must be able to tell why each item is there.
1. **Result.** The versions now installed and `git diff --stat`. Everything is uncommitted. Suggest 3 commits, each with its `git add` paths: - the dependency bump; - the migrations folder conversion; - the required code changes.
Also give the command that undoes the whole upgrade.2. **Migrations folder.** Folders converted, the SQL integrity result, and the `check` / `generate` results.3. **Required code changes.** One entry per kind of change: the file paths, then Why / Doc / Evidence.4. **Validation.** A table of each command, before and after.5. **Not changed, for you to decide.** - Deprecated APIs, with the replacement and Why / Doc / Evidence. - Scripts, CI and Docker steps, with the suggested replacement and Why / Doc / Evidence. - Custom type parsers and `schemaFilter`. - Relational queries changed. - Any mismatch between this prompt and the installed code, and anything you could not verify.6. **Before you run migrations (your responsibility).** - Back up the database first. - Production: test on a local copy or a staging database, never straight on production. - The first v1 `migrate()` (or `drizzle-kit migrate`) alters the migrations table and backfills a `name` for each applied migration. **It throws if the database holds a migration that has no matching local folder.** See https://orm.drizzle.team/docs/v0-v1-changes#updates-to-the-migration-table. Compare the row count of `__drizzle_migrations` (Postgres: `drizzle.__drizzle_migrations`) with the number of local migration folders. - v1 applies every local migration missing from the database, even one older than the last applied. 0.x skipped those. Check that no local migration was intentionally left unapplied. See https://orm.drizzle.team/docs/v0-v1-changes#migrator-applies-all-missing-migrations. - Deploy the code and the converted folder together. The 0.x migrator cannot read the new layout, and the v1 migrator refuses a folder that still has `meta/_journal.json`.7. **Optional:** to keep Drizzle's agent skills in this project, run `npx drizzle-kit skills` yourself. It runs `npx -y skills@latest add` and asks which agents to install for.Already fixed on rc5
These rc.4 bugs are fixed on the rc5 branch and ship with rc.5 (drizzle-orm#5966 (GitHub pull request, opens in a new tab)). Their issues stay open until the release, so each line links the fix commit or the changelog entry. You can find the full lists in the drizzle-orm changelog (GitHub, opens in a new tab) and the drizzle-kit changelog (GitHub, opens in a new tab).
drizzle-orm
- postgres-js:
drizzle()no longer breaks the driver’s serializers fortimestamp,timestamptz,date,time,jsonandjsonb(drizzle-orm#3171 (GitHub issue, opens in a new tab), drizzle-orm#4426 (GitHub issue, opens in a new tab), drizzle-orm#5789 (GitHub issue, opens in a new tab); commit32a8fd8(GitHub, opens in a new tab)). - node-postgres transactions: no more process crash when the connection drops mid-transaction, and no more leaked pool client when
BEGINfails (drizzle-orm#6437 (GitHub issue, opens in a new tab), drizzle-orm#6341 (GitHub issue, opens in a new tab), drizzle-orm#6023 (GitHub issue, opens in a new tab), drizzle-orm#6241 (GitHub issue, opens in a new tab), drizzle-orm#6114 (GitHub issue, opens in a new tab); commit5ca1b68(GitHub, opens in a new tab), changelog (GitHub, opens in a new tab)). - Batch inserts with more than about 120k params no longer crash with a
RangeError(drizzle-orm#5994 (GitHub issue, opens in a new tab); changelog (GitHub, opens in a new tab)). - Relational query configs type-check again with TypeScript 6 (drizzle-orm#5644 (GitHub issue, opens in a new tab), drizzle-orm#6383 (GitHub issue, opens in a new tab); commit
bc1049d(GitHub, opens in a new tab)). $onUpdateFnno longer runs when it does not need to (drizzle-orm#5780 (GitHub issue, opens in a new tab); changelog (GitHub, opens in a new tab)).- MySQL
datecolumns no longer shift with the server’s timezone (drizzle-orm#1442 (GitHub issue, opens in a new tab); commitd190636(GitHub, opens in a new tab)).
drizzle-kit
generateno longer drops a column before its index, which failed on Postgres with error 42704 (drizzle-orm#6045 (GitHub issue, opens in a new tab); changelog (GitHub, opens in a new tab)).- No more false schema changes on default values, and valid defaults for sequence-based primary keys (drizzle-orm#5569 (GitHub issue, opens in a new tab), drizzle-orm#5413 (GitHub issue, opens in a new tab); changelog L8 (GitHub, opens in a new tab), L11 (GitHub, opens in a new tab)).
generatekeeps a column change when a column with the same name is renamed in another table (drizzle-orm#6360 (GitHub issue, opens in a new tab); changelog (GitHub, opens in a new tab)).- Turning a view into a materialized view generates the right migration (drizzle-orm#6176 (GitHub issue, opens in a new tab); changelog (GitHub, opens in a new tab)).
pushno longer tries to drop Neon system roles withprovider: "neon"(drizzle-orm#6105 (GitHub issue, opens in a new tab); changelog (GitHub, opens in a new tab)).pullhonors theschemaFiltersCLI flag (drizzle-orm#3626 (GitHub issue, opens in a new tab); changelog (GitHub, opens in a new tab)).- PGlite accepts custom options in the config (drizzle-orm#2995 (GitHub issue, opens in a new tab); drizzle-orm#6190 (GitHub pull request, opens in a new tab)).
Moving from rc.4 to rc.5
rc.5 is not a drop-in bump, it changes some rc.4 behavior. The rc.5 prompt will cover it. Until then, here is what to know:
- postgres-js: remove manual
JSON.stringifyon JSON params in raw SQL or raw driver calls, or the value is stringified twice. Pass array JSON params assql.param(value). undefinedin a relational querywherenow throws (drizzle-orm#5636 (GitHub issue, opens in a new tab)). UseEmptyFilterwhen a filter is optional on purpose.withReplicassends every query to the primary by default. Calldb.$replicato read from a replica (drizzle-orm#6279 (GitHub pull request, opens in a new tab)).DrizzleQueryErrorno longer includes query params. SetparamsInErrors: trueindrizzle()to get them back (drizzle-orm#5939 (GitHub issue, opens in a new tab); commit8e78e2b(GitHub, opens in a new tab)).
Known and still open
Already reported, still present on the rc5 branch. Add details to the existing issue or pull request rather than opening a new issue.
drizzle-kit migrateruns the full commutativity check on every run, even with nothing to apply (drizzle-orm#5777 (GitHub issue, opens in a new tab), fix proposed in drizzle-orm#6138 (GitHub pull request, opens in a new tab)).- drizzle-kit does not declare drizzle-orm as a peer dependency (drizzle-orm#5573 (GitHub issue, opens in a new tab)).
- Reported in drizzle-orm#6443 (GitHub pull request, opens in a new tab) (fix proposed, open): after
up, the firstgeneratecan rebuild indexes with.with(...), partial indexes and check constraints. Ifgeneratewrites a migration right afterup, read it before you keep it. - Migration folder names can be a year off around New Year, depending on the machine’s timezone (drizzle-orm#6455 (GitHub issue, opens in a new tab), fix proposed in drizzle-orm#6454 (GitHub pull request, opens in a new tab)).