Database Migration Workflow (/db-migration) — express¶
Stack flavor: express. ← Back to overview
[!CAUTION] Mandatory for ANY change to the database schema. Follow every step to prevent data loss or drift.
Trigger Conditions¶
- Files: Changes to
backend/src/db/schema.ts - Keywords: "Add a column", "New table", "Change database", "Migration"
1. Schema Update¶
- [ ] Drizzle: Modify
backend/src/db/schema.ts - Always use
uuidtype for primary and foreign keys — neverTEXT - Follow existing table patterns in the file
- [ ] Types: Update any TypeScript interfaces that reflect the DB structure
2. Generation¶
-
[ ] Command: Run the migration generator:
This runscd backend && npm run migrate:generatedrizzle-kit generateand outputs a.sqlfile tobackend/migrations/ -
[ ] Review (CRITICAL): Open the generated
.sqlfile and verify: - No unexpected
DROPstatements — if you see any, investigate before proceeding - Manual
IF NOT EXISTSguards: drizzle-kit does NOT add these automatically — you MUST add them:CREATE TABLE IF NOT EXISTSALTER TABLE ... ADD COLUMN IF NOT EXISTSCREATE INDEX IF NOT EXISTS
- Complex constraints: Wrap in
DO $$ ... END $$blocks to handle duplicates gracefully - See
.agent/rules/migration-safety.mdfor the full idempotency rules
3. Application¶
-
[ ] Apply locally:
This runscd backend && npm run migrate:devtsx src/migrate.tsagainst your local/dev database -
[ ] Verification: Query the database (or run
cd backend && npm run db:studio) to confirm the new structure exists
4. Backend Update¶
- [ ] Drizzle Queries: Update routes in
backend/src/routes/to use the new fields/tables - [ ] Validation: Update Zod schemas in the affected route file to include new fields
- [ ] Types: Confirm Drizzle's inferred TypeScript types are correct (
cd backend && npm run type-check)
5. Production¶
- [ ] Build:
cd backend && npm run build - [ ] Deploy: The production migration runs via
npm run migrate(node dist/src/migrate.js) on startup