Docs / Database / Migrations
Migrations
Schema changes go through bun run db:generate then bun run db:migrate, not db:push.
Why not db:push
drizzle-kit push diffs your schema against the live database and applies the result directly, no SQL file, no history. Against a Supabase-hosted Postgres it crashes introspecting CHECK constraints on system schemas (auth, storage, extensions) with an unrelated TypeError, regardless of the schemaFilter in drizzle.config.ts. db:generate + db:migrate avoid touching those schemas at all, generate only ever reads public (per schemaFilter: ["public"]), and migrate just replays SQL.
The normal path
bun run db:generate # writes lib/db/migrations/NNNN_name.sql + meta/NNNN_snapshot.json
bun run db:migrate # applies pending migrations to DATABASE_URL
db:generate diffs your schema files against the last snapshot and writes a plain SQL migration plus a metadata snapshot Drizzle uses for the next diff. db:migrate applies whatever hasn't run yet, tracked in a __drizzle_migrations table it creates on first run.
drizzle-kit generate needs a TTY
When a schema diff is ambiguous, renaming a column, or sometimes just adding one, generate prompts interactively to resolve it. That prompt doesn't work in a non-interactive shell (CI, some AI coding assistants' sandboxed shells), and it fails outright rather than guessing.
If generate won't run non-interactively
Hand-write the migration instead of fighting the prompt:
- Write the migration SQL yourself, a plain
ALTER TABLE/CREATE TABLEstatement matching what you changed in the schema file. - Generate the matching
meta/NNNN_snapshot.jsonprogrammatically, viadrizzle-kit/api'sgenerateDrizzleJson, not freehand. The snapshot has to reflect the exact post-migration schema shape for the nextdb:generateto diff against correctly. - Add an entry to
lib/db/migrations/meta/_journal.jsonmatching the existing entries' shape. - Run
bun run db:migrateas normal, it replays SQL, it doesn't care whether the file was generated or hand-written.
This is the same workaround used throughout Keel's own build (billing column renames, a plain column add, several new columns at once), it's about the hand-written snapshot's shape in general, not just rename ambiguity.