This project uses Cloudflare D1 migrations with automatic tracking. D1 records which migrations have been applied in a d1_migrations table so they are never re-run.
NEVER modify a migration file that has already been applied in production.
Applied migrations are immutable. If you need to change the schema, create a NEW migration file with the next sequence number. Editing an old migration will cause checksum mismatches, break deployments, and potentially corrupt production data.
- Any migration file already committed to
mainshould be treated as applied in production. - Run
npm run db:migrate:listto see which migrations have been applied. - When in doubt, assume it has been applied and create a new migration instead.
- Create a new file with the next sequential number:
NNNN_description.sql - Use
ALTER TABLEto modify existing tables, notCREATE TABLE - Use
IF NOT EXISTS/IF EXISTSguards where appropriate - Keep migrations small and focused - one logical change per file
- Edit or delete any existing migration file (e.g.,
0001_initial_schema.sql) - Reorder or renumber migration files
- Combine multiple migrations into one
- Add
DROP TABLEwithout explicit user confirmation - Modify the
d1_migrationstracking table
NNNN_short_description.sql
NNNN= zero-padded sequence number (0001, 0002, 0003, ...)short_description= lowercase snake_case description of the change- Examples:
0001_initial_schema.sql0002_add_user_preferences.sql0003_add_index_on_email.sql
# Apply all pending migrations to remote D1
npm run db:migrate
# Apply all pending migrations to local D1
npm run db:migrate:local
# List migrations and their status (applied / pending)
npm run db:migrate:listCloudflare D1's built-in migration system:
- Reads all
.sqlfiles from themigrations/directory - Sorts them by filename (sequential numbering)
- Checks the
d1_migrationstable to see which have already been applied - Applies only the pending migrations in order
- Records each successful migration in
d1_migrations
Migrations that have already run are skipped automatically - they will never execute twice.
- Find the highest existing migration number
- Create a new file with the next number:
migrations/NNNN_your_change.sql - Write your SQL (ALTER TABLE, CREATE TABLE, CREATE INDEX, etc.)
- Test locally:
npm run db:migrate:local - Verify:
npm run db:migrate:list - Commit and deploy
| File | Description |
|---|---|
0001_initial_schema.sql |
Base tables: users, sessions, oauth_accounts, chat_messages, indexes |