Skip to content

docs(d1): add baseline migration pattern for existing databases#31812

Draft
ivoryibu wants to merge 2 commits into
productionfrom
docs/d1-baseline-migration
Draft

docs(d1): add baseline migration pattern for existing databases#31812
ivoryibu wants to merge 2 commits into
productionfrom
docs/d1-baseline-migration

Conversation

@ivoryibu

Copy link
Copy Markdown
Collaborator

Summary

Adds a new section to the D1 migrations page documenting how to adopt the migration system on an existing database that already has tables.

Problem

The current migrations documentation assumes you are starting from scratch. Developers who have an existing D1 database with tables and want to start using wrangler d1 migrations have no guidance on how to create a baseline migration that captures the current schema without breaking anything.

Changes

Adds an "Adopt migrations on an existing database" section to src/content/docs/d1/reference/migrations.mdx that covers:

  • When a baseline migration is useful (teams, CI/CD, schema history) and when you can skip it (solo developer, single database)
  • How to export the current schema with sqlite_master
  • How to create a baseline migration using CREATE TABLE IF NOT EXISTS so it is safe to apply against the live database
  • How to apply locally and remotely

Context

Discovered during hands-on testing of D1 schema management workflows. The CREATE TABLE IF NOT EXISTS pattern ensures the migration records itself in d1_migrations without attempting to recreate tables that already exist.

@cloudflare-docs-bot

cloudflare-docs-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review

⚠️ 2 warnings found in commit 5c4e5aa.

Code Review

This code review is in beta and may not always be helpful — use your judgment.

Warnings (2)
File Issue
d1/reference/migrations.mdx line 99 Incorrect schema filtername NOT LIKE '_cf%' treats _ as a single-character wildcard in SQLite, so it excludes any table whose second character is c and third is f (for example, xcf_users), not just Cloudflare internal _cf_\* tables. Fix: Replace the filter with name NOT GLOB '_cf\*' (GLOB treats _ literally) or name NOT LIKE '\_cf\_%' ESCAPE '\' to match the actual internal-table prefix.
d1/reference/migrations.mdx line 99 Incomplete schema capture — The query filters type='table', so existing indexes, views, and triggers are not captured. A database recreated from this baseline will differ from the source (e.g., missing unique indexes), yet the surrounding text calls this a "complete schema history". Fix: Extend the query to include type IN ('table','index','view','trigger') and add IF NOT EXISTS to the generated statements, or explicitly note that the baseline only covers tables.

Conventions

Checks PR title, description, and redirect checklist.

No convention issues found.

Style Guide Review

No style-guide issues found.

Redirects

No missing redirect entries found.

Commands

Only codeowners can run commands. Post a comment with the command to trigger it.

Command Description
/review Runs a review now. Incremental if a prior review exists, full if not.
/full-review Re-reviews the entire PR diff from scratch, ignoring incremental history. Useful after a rebase, when you want a fresh review, or if the bot gets out of sync and reports issues that no longer exist.
/ignore-review-limit Permanently lifts the 2-review automatic limit for this PR. Future pushes will trigger reviews as normal.
/disable-auto-review Stops automatic reviews from triggering on future pushes to this PR. Codeowners can still run /review or /full-review manually.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request requires reviews from CODEOWNERS as it changes files that match the following patterns:

Pattern Owners
/src/content/docs/d1/ @elithrar, @rita3ko, @irvinebroque, @vy-ton, @ivoryibu, @rts-rob, @joshthoward, @lambrospetrou, @oxyjun, @cloudflare/product-owners

@ask-bonk ask-bonk Bot added documentation Documentation edits triage Waiting for a docs team review. content:new Request for new/missing content labels Jun 30, 2026

@ask-bonk ask-bonk Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue needs fixing and 2 suggestions posted.

MEDIUM — Multi-step procedures must use the <Steps> component instead of a bare numbered list.

HIGH — The sqlite_master query only captures tables, missing indexes, views, and triggers. A baseline created from this output will be incomplete for databases that use those features.

LOW — Step 3 mixes action and explanation in one long sentence.

(Note: the import for Steps must also be added on line 11, but that line was not changed in this PR so an inline suggestion could not be posted there.)

Comment on lines +95 to +124
1. Get your current schema:

```sh
npx wrangler d1 execute <DATABASE_NAME> --remote \
--command="SELECT sql FROM sqlite_master WHERE type='table' AND name NOT LIKE '_cf%' AND name != 'sqlite_sequence'"
```

2. Create a baseline migration:

```sh
npx wrangler d1 migrations create <DATABASE_NAME> baseline
```

3. Paste your existing `CREATE TABLE` statements into the file, adding `IF NOT EXISTS` so the migration is safe to run against the live database that already has these tables:

```sql
-- migrations/0001_baseline.sql
CREATE TABLE IF NOT EXISTS users (
user_id INTEGER PRIMARY KEY,
email TEXT NOT NULL,
name TEXT
);
```

4. Apply locally and remotely:

```sh
npx wrangler d1 migrations apply <DATABASE_NAME> --local
npx wrangler d1 migrations apply <DATABASE_NAME> --remote
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap the procedure in <Steps> (import it from ~/components on line 11):

Suggested change
1. Get your current schema:
```sh
npx wrangler d1 execute <DATABASE_NAME> --remote \
--command="SELECT sql FROM sqlite_master WHERE type='table' AND name NOT LIKE '_cf%' AND name != 'sqlite_sequence'"
```
2. Create a baseline migration:
```sh
npx wrangler d1 migrations create <DATABASE_NAME> baseline
```
3. Paste your existing `CREATE TABLE` statements into the file, adding `IF NOT EXISTS` so the migration is safe to run against the live database that already has these tables:
```sql
-- migrations/0001_baseline.sql
CREATE TABLE IF NOT EXISTS users (
user_id INTEGER PRIMARY KEY,
email TEXT NOT NULL,
name TEXT
);
```
4. Apply locally and remotely:
```sh
npx wrangler d1 migrations apply <DATABASE_NAME> --local
npx wrangler d1 migrations apply <DATABASE_NAME> --remote
```
<Steps>
1. Get your current schema:
```sh
npx wrangler d1 execute <DATABASE_NAME> --remote \
--command="SELECT sql FROM sqlite_master WHERE type='table' AND name NOT LIKE '_cf%' AND name != 'sqlite_sequence'"
```
2. Create a baseline migration:
```sh
npx wrangler d1 migrations create <DATABASE_NAME> baseline
```
3. Paste your existing `CREATE TABLE` statements into the file. Add `IF NOT EXISTS` to each statement so the migration is safe to run against a live database:
```sql
-- migrations/0001_baseline.sql
CREATE TABLE IF NOT EXISTS users (
user_id INTEGER PRIMARY KEY,
email TEXT NOT NULL,
name TEXT
);
```
4. Apply locally and remotely:
```sh
npx wrangler d1 migrations apply <DATABASE_NAME> --local
npx wrangler d1 migrations apply <DATABASE_NAME> --remote
```
</Steps>


```sh
npx wrangler d1 execute <DATABASE_NAME> --remote \
--command="SELECT sql FROM sqlite_master WHERE type='table' AND name NOT LIKE '_cf%' AND name != 'sqlite_sequence'"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This query captures only tables, so the baseline will miss indexes, views, and triggers. Consider expanding the query or adding a note that other schema objects must be captured separately.

@ask-bonk

ask-bonk Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review complete for PR #31812.

Labels applied: documentation, triage, content:new

Summary of changes:
Adds a 4-step procedure to src/content/docs/d1/reference/migrations.mdx showing how to create a baseline migration for an existing D1 database using sqlite_master and CREATE TABLE IF NOT EXISTS.

Issues flagged:

  • MEDIUM — The multi-step procedure must use the <Steps> component per style guide requirements. Posted an inline suggestion wrapping the numbered list and noted that Steps also needs to be added to the import on line 11.
  • HIGH — The sqlite_master query filters on type='table', so it misses indexes, views, and triggers. A baseline built from this output will be incomplete for databases that rely on those objects.
  • LOW — Step 3 combines the action and explanation in a long sentence; could be tighter.

Validation results:

  • pnpm run check — passed (0 errors)
  • pnpm run format:core:check — passed
  • No MDX syntax issues, broken links, or unescaped characters detected
  • No missing component imports for content added in this PR

Review posted: #31812 (review)

github run

@ivoryibu ivoryibu marked this pull request as draft June 30, 2026 19:33
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

content:new Request for new/missing content documentation Documentation edits product:d1 D1: https://developers.cloudflare.com/d1/ size/s triage Waiting for a docs team review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants