What this usually means
Drizzle Kit relies on a snapshot file (usually `drizzle-kit.json` or `meta/_journal.json`) that tracks the last known state of your database schema. When you modify your schema in TypeScript and run a command, Drizzle compares the new schema against this snapshot. If the snapshot is stale, corrupted, or missing, Drizzle may think nothing changed. This can happen after a branch switch, manual database edits, or if the snapshot was deleted or not committed. Another common cause is misconfiguration in `drizzle.config.ts` — wrong `out` directory, incorrect `schema` glob, or missing `dbCredentials` can cause the tool to look at the wrong files or database.
The first ten minutes — establish facts before touching code.
- 1Check `drizzle.config.ts` or `drizzle.config.js` for correct `schema`, `out`, and `dbCredentials` values.
- 2Look at the snapshot file (default: `drizzle-kit.json` or `meta/_journal.json`). Verify the timestamp and compare with your last migration.
- 3Run `drizzle-kit introspect` to see what Drizzle reads from the database. Compare with your schema.ts.
- 4Inspect generated SQL in the `out` directory. If it's empty, the snapshot is likely the issue.
- 5Check if the snapshot file is in `.gitignore` or has been overwritten by a branch merge.
The specific files, logs, configs, and dashboards that usually own this bug.
- search`drizzle.config.ts` or `drizzle.config.js`
- search`drizzle-kit.json` (default snapshot file)
- search`meta/_journal.json` (if using Drizzle Kit v0.2+)
- search`out/` directory containing generated SQL migration files
- search`schema.ts` or wherever you define your Drizzle schema
- searchpackage.json scripts (verify the correct Drizzle Kit version)
- searchDatabase logs (e.g., PostgreSQL logs for DDL statements)
Practical causes, not theory. These are the things you will actually find.
- warningSnapshot file not updated after manual database changes (e.g., adding a column via SQL console)
- warningMismatch between `schema` glob pattern and actual schema file path
- warningMultiple schema files with conflicting table definitions
- warningDrizzle Kit version mismatch between local and CI or between team members
- warningSnapshot file committed to git but not regenerated after a rebase or merge conflict
- warningDatabase connection string pointing to a different database (e.g., staging vs local)
- warningUsing `drizzle-kit push` without first running `drizzle-kit introspect` after a fresh clone
Concrete fix directions. Pick the one that matches your root cause.
- buildRun `drizzle-kit introspect` to update the snapshot from the current database state, then re-run `push`.
- buildDelete the snapshot file and regenerate it: `rm drizzle-kit.json && drizzle-kit introspect`.
- buildEnsure `drizzle.config.ts` has the correct `schema` path (e.g., `'./src/db/schema.ts'`) and `out` directory.
- buildIf using version control, commit the snapshot file and ensure all team members regenerate after pulling.
- buildFor complex changes, generate a migration file manually: `drizzle-kit generate` and then `drizzle-kit migrate`.
- buildUpgrade to the latest Drizzle Kit version to avoid known bugs (check changelog for snapshot-related fixes).
A fix you cannot prove is a guess. Close the loop.
- verifiedRun `drizzle-kit introspect` and compare the output snapshot with your schema.ts — they should match.
- verifiedAfter fix, run `drizzle-kit push` and confirm it outputs the expected SQL (e.g., 'ALTER TABLE ... ADD COLUMN').
- verifiedCheck the database directly: do the schema changes exist? Query `information_schema.columns` for verification.
- verifiedRun `drizzle-kit generate` and inspect the generated SQL file in the `out` directory.
- verifiedRe-run your test suite that depends on the new schema (e.g., insert a row into the new column).
Things that make this bug worse or harder to find.
- warningEditing the snapshot file manually to try to trick Drizzle into detecting changes — it will just cause corruption.
- warningIgnoring the snapshot file in `.gitignore` — it must be tracked if you want consistent team behavior.
- warningRunning `push` on a production database without first testing on a staging environment.
- warningAssuming `drizzle-kit push` is safe — it can drop columns or tables if schema changes are destructive.
- warningUsing `--force` flag without understanding why the snapshot is out of sync.
- warningNot reading the Drizzle Kit console output: it often prints warnings about snapshot mismatch.
The Phantom Schema Change: Drizzle Pushes Nothing
Timeline
- 09:15Developer A adds a `phone` column to the `users` table in schema.ts.
- 09:20Developer A runs `drizzle-kit push` — outputs 'No schema changes detected'.
- 09:25Developer A verifies database: `phone` column does not exist.
- 09:30Developer A checks `drizzle-kit.json` — snapshot shows old schema without `phone`.
- 09:35Developer A runs `drizzle-kit introspect` — snapshot updates, now includes `phone`.
- 09:36Developer A runs `drizzle-kit push` — successfully adds the column.
- 09:40Developer A commits the updated snapshot file.
- 10:00CI pipeline runs `drizzle-kit push` on staging — works fine because snapshot is committed.
I had just added a `phone` column to the `users` table in our schema.ts. Simple enough. I ran `drizzle-kit push` expecting it to create an ALTER TABLE statement. Instead, the console printed 'No schema changes detected'. I stared at the screen for a good 30 seconds. I knew I had changed the file — I even double-checked the diff. The column was there in code, but Drizzle was ignoring it.
I checked the `drizzle-kit.json` file. It contained the old schema snapshot — no `phone` column. That was the problem. Drizzle Kit uses that snapshot as the baseline to compute the diff. If the snapshot is stale, it thinks nothing changed. I had made the mistake of not running `introspect` after a previous manual database edit, so the snapshot was out of date even before I made my change.
The fix was straightforward: `drizzle-kit introspect` to pull the actual current schema from the database into the snapshot. Then `push` worked perfectly. I also learned to commit the snapshot file to version control so that CI and other developers stay in sync. The whole ordeal took 20 minutes because I didn't immediately check the snapshot — now it's the first thing I look at.
Root cause
Stale snapshot file (`drizzle-kit.json`) that was not updated after a previous manual schema change, causing Drizzle Kit to compute a diff against an incorrect baseline.
The fix
Ran `drizzle-kit introspect` to regenerate the snapshot from the current database state, then re-ran `push`. Committed the updated snapshot to git.
The lesson
Always keep your snapshot file in sync with the actual database. After any manual DDL change, run `introspect` before your next `push`. Track the snapshot in version control.
Drizzle Kit uses a JSON snapshot file (default `drizzle-kit.json` in v0.1.x, or a `meta/_journal.json` + `meta/` folder in newer versions) to remember what your database schema looked like the last time you ran an introspection or migration. When you run `push` or `generate`, it compares your TypeScript schema against this snapshot to compute the needed DDL.
If the snapshot is missing, outdated, or corrupted, Drizzle cannot detect differences. This is the #1 cause of 'no changes detected' errors. The snapshot should be treated as a source-of-truth artifact — commit it to git, regenerate it after any manual database changes, and never edit it by hand.
Your `drizzle.config.ts` file is the backbone. A common mistake is having the `schema` glob not matching any files (e.g., `'./src/schema/*.ts'` when your files are in `./src/db/schema.ts`). Drizzle will silently use an empty schema, and the snapshot will remain unchanged. Always verify the schema path by running `drizzle-kit introspect` and checking if it reads your tables.
Another issue is `dbCredentials` pointing to the wrong database — for example, a connection string with an environment variable that resolves to `localhost` in development but to a production URL in CI. Always log or print the connection string during debugging (but sanitize credentials). Use `drizzle-kit introspect` with explicit `--config` to test.
When multiple developers work on schema changes in parallel, the snapshot file can become a source of merge conflicts. A common scenario: Developer A adds a column and commits the updated snapshot. Developer B, on a different branch, also adds a column and commits a different snapshot. When merging, git may produce a conflicted snapshot file that Drizzle cannot parse.
The fix is to resolve the merge conflict in the snapshot file (it's JSON, so you can merge manually) or, more safely, delete the snapshot, run `drizzle-kit introspect` against the merged database state, and generate a fresh snapshot. Also consider using `drizzle-kit generate` instead of `push` to produce SQL migration files that are less prone to conflict.
If anyone runs a raw SQL command on the database (e.g., `ALTER TABLE users ADD COLUMN email text;`), the snapshot file is not automatically updated. Next time you run `drizzle-kit push`, it will compare your schema (which might already have that column) against the old snapshot (which doesn't), leading to a false 'no changes' or attempting to add an existing column.
Best practice: after any manual DDL, immediately run `drizzle-kit introspect` to re-sync the snapshot. Alternatively, enforce that all schema changes go through Drizzle migrations. In a team, add a CI check that verifies the snapshot matches the database schema before allowing deployments.
Drizzle Kit has undergone several major version bumps (0.16, 0.17, 0.18+). The snapshot format changed significantly between versions. If one developer uses `drizzle-kit@0.17` and another uses `0.18`, the snapshot file generated by one may be incompatible with the other. This can cause parsing errors or silent failures.
Always lock your Drizzle Kit version in `package.json` (e.g., `"drizzle-kit": "0.18.0"`). When upgrading, read the changelog for migration instructions — often you need to delete the old snapshot and regenerate it. In CI, ensure the exact same version is used as in development.
Frequently asked questions
Why does `drizzle-kit push` say 'no changes' even though I just added a table?
Most likely the snapshot file (`drizzle-kit.json` or `meta/_journal.json`) is out of sync. Run `drizzle-kit introspect` to update the snapshot from the current database, then run `push` again. Also check that your schema file is correctly referenced in `drizzle.config.ts` and that the glob pattern matches.
Should I commit the snapshot file to git?
Absolutely. The snapshot is essential for consistent team development and CI/CD. If you don't commit it, every developer and CI pipeline will have a different baseline, leading to unpredictable migration behavior. Just be aware that merge conflicts can occur; resolve them carefully or regenerate the snapshot after merge.
How do I fix a corrupted snapshot file?
Delete the snapshot file (e.g., `rm drizzle-kit.json` or `rm -rf meta/`) and then run `drizzle-kit introspect` to regenerate it from the current database state. Make sure your database is in a known good state before doing this. Then run `drizzle-kit generate` to produce any pending migrations.
What's the difference between `drizzle-kit push` and `drizzle-kit migrate`?
`push` directly applies schema changes to the database by computing a diff between your schema and the snapshot. It's fast but can be destructive (e.g., dropping columns). `migrate` runs SQL files generated by `drizzle-kit generate`, which gives you more control and a reproducible audit trail. Use `push` for rapid prototyping, `migrate` for production.
Can I use Drizzle Kit with MySQL or SQLite?
Yes. Drizzle ORM supports PostgreSQL, MySQL, SQLite, and others. The migration commands work similarly, but the generated SQL dialect will differ. The snapshot-based debugging approach is the same across all supported databases.