How-to guides
Database migrations
Generate, apply, and deploy Drizzle migrations for Cloudflare D1.
Schema lives in packages/db (Drizzle ORM on D1/SQLite). Migrations are
generated files — never hand-edit them.
Generate
After changing schema in packages/db/src:
bun run db:generate # → packages/db/drizzle/*.sql + metaCommit the generated migration alongside the schema change.
Apply locally
cd apps/web
bun run db:migrate:local # wrangler d1 migrations apply ktb --localApply to production
cd apps/web
bun run db:migrate # wrangler d1 migrations apply ktb --remoteDeploy-time sync
bun run deploy (root) → infra:deploy in apps/web runs
sync-alchemy-migrations.mjs first — it mirrors
Drizzle migrations into packages/db/alchemy-migrations so Alchemy-managed
environments stay in sync. If you see drift between the two directories, rerun
the sync script rather than editing files by hand.
Rules
- Migrations are append-only in effect: once applied to prod, fix forward with a new migration — don't edit applied SQL.
- The same schema must work on D1 (prod/local) and the Node dev path — avoid SQLite-isms that only work on one.