Authoring D1 migrations
August 25, 2026 ยท View on GitHub
Naming, ledger rules, and what not to edit after a migration lands. See the setup index for the other setup pages. Remote apply examples live in Seed test account.
- New migration files live in
packages/worker/migrations/and are applied in lexicographic filename order by Wrangler (npm run migrate:local,migrate:e2e, and the documentedd1 migrations apply APP_DB --remoteinvocations in Seed test account). - Name new files
NNNN-kebab-case-description.sql(four-digit prefix, hyphen, kebab-case slug). Pick the next prefix as(max numeric prefix) + 1, zero-padded to four digits (for example, if the highest prefix is0075, use0076-my-change.sql). - If your branch is behind
mainand a new migration has landed upstream with the prefix you picked, rebase and renumber your file to a new unused prefix. Do not introduce new duplicate prefixes. - Do not edit migration files that have already landed in
mainand been deployed. New migration files that only exist on your branch can be revised freely until they land inmain; once deployed, any schema correction should ship as a new migration instead. npm run migrations:check(also run bynpm run validateand the pre-commit hook) enforces the naming rules above against the checked-in, append-onlytools/migration-ledger.json. When adding a migration, append its filename and SHA-256 digest to the ledger; never edit or remove an existing ledger entry. The check compares historical entries and SQL contents with a pre-change Git commit: CI supplies the PR base or push-before SHA, local branches use theirmainmerge base, and main/detached checkouts fall back to the first parent.HEADitself is never trusted. CI fetches complete history; local and cloud checkouts must retain or fetchorigin/main. If no pre-change commit is available, validation fails safely once migrations exist beyond the frozen bootstrap baseline. Migration SQL is hashed with canonical LF line endings, and.gitattributesenforces LF checkouts.- Duplicate prefixes are always rejected. The 2026-08-04 migration-history
squash collapsed the pre-launch history into
0001-squashed-init.sql(full schema plus migration-seeded platform rows); the pre-squash files remain in Git history only.tools/ci/reset-migration-bookkeeping.tsis the deterministic guard that rewroted1_migrationsbookkeeping in existing databases โ it verifies the applied set matches the frozen pre-squash list exactly before touching anything, and no-ops on fresh or already-squashed databases. The guard runs only for local applies against pre-squash developer state dirs; delete it once those have died out. - Leftovers this migration cannot drop yet (old columns, dual-write, a later
deleted_classestag, a soak) follow Cleanup after migrations: remove them in this change when safe, otherwise open a GitHub issue.