Skip to content

docs(d1): add complete guide to d1#31263

Draft
ivoryibu wants to merge 1 commit into
productionfrom
add-d1-complete-guide
Draft

docs(d1): add complete guide to d1#31263
ivoryibu wants to merge 1 commit into
productionfrom
add-d1-complete-guide

Conversation

@ivoryibu
Copy link
Copy Markdown
Collaborator

@ivoryibu ivoryibu commented Jun 5, 2026

Summary

This documentation adds a comprehensive, end-to-end tutorial titled "D1 Complete Guide" (d1-complete-guide.mdx) under the D1 best practices section.

The guide provides developers with a structured workflow for implementing Cloudflare D1 in production environments, filling the gap between a basic quick-start tutorial and isolated optimization tips.

Key Sections Included:

  • Architecture & Mechanics: Explains how D1 leverages the Cloudflare global network to provide low-latency serverless SQL databases.
  • Workflow Optimization: Step-by-step guidance on setting up local vs. remote development environments, configuring wrangler.toml, and handling schema migrations securely.
  • Data Resiliency & Querying: Outlines patterns for robust querying, handling common database constraint errors, and executing safe data mutations.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

CI run failed: build logs

@ivoryibu ivoryibu marked this pull request as ready for review June 5, 2026 19:49
@cloudflare-docs-bot
Copy link
Copy Markdown
Contributor

cloudflare-docs-bot Bot commented Jun 5, 2026

Review

⚠️ 31 warnings and 2 suggestions found in commit 3bbb861.

Warnings (31)
File Issue
d1/best-practices/d1-complete-guide.mdx line 1 No H1 in body — Line adds # The Complete Guide to Cloudflare D1 as a body H1 Fix: Change to ## The Complete Guide to Cloudflare D1 and rely on frontmatter title for the H1
d1/best-practices/d1-complete-guide.mdx line 415 Contractions — Line adds don't in prose Fix: Remove the contraction: do not
d1/best-practices/d1-complete-guide.mdx line 627 Contractions — Line adds Can't in a heading Fix: Remove the contraction: Cannot
d1/best-practices/d1-complete-guide.mdx line 640 Contractions — Line adds doesn't in prose Fix: Remove the contraction: does not
d1/best-practices/d1-complete-guide.mdx line 59 Bold tool/program name — Line adds \*\*SQLite\*\* (a program name) in bold Fix: Use monospace instead: `SQLite`
d1/best-practices/d1-complete-guide.mdx line 79 Internal link uses full URL — Line adds an image link with https://developers.cloudflare.com/images/d1/d1-read-replication-concept.png Fix: Use root-relative path: /images/d1/d1-read-replication-concept.png
d1/best-practices/d1-complete-guide.mdx line 305 Internal link uses full URL — Line adds [error list](https://developers.cloudflare.com/d1/observability/debug-d1/#error-list) Fix: Use root-relative path: [/d1/observability/debug-d1/#error-list]
d1/best-practices/d1-complete-guide.mdx line 397 Internal link uses full URL — Line adds [Time Travel](https://developers.cloudflare.com/d1/reference/time-travel/) Fix: Use root-relative path: [/d1/reference/time-travel/]
d1/best-practices/d1-complete-guide.mdx line 438 Internal link uses full URL — Line adds an image link with https://developers.cloudflare.com/images/d1/consistency-with-sessions-api.png Fix: Use root-relative path: /images/d1/consistency-with-sessions-api.png
d1/best-practices/d1-complete-guide.mdx line 494 Internal link uses full URL — Line adds an image link with https://developers.cloudflare.com/images/d1/consistency-without-sessions-api.png Fix: Use root-relative path: /images/d1/consistency-without-sessions-api.png
d1/best-practices/d1-complete-guide.mdx line 746 Internal link uses full URL — Line adds an Additional Resources link with https://developers.cloudflare.com/... Fix: Use a root-relative path instead
d1/best-practices/d1-complete-guide.mdx line 114 Heading uses -ing verb — Line adds ## Getting Started in 5 Minutes Fix: Use imperative form: ## Get started in 5 minutes
d1/best-practices/d1-complete-guide.mdx line 498 Heading uses -ing verb — Line adds ### Enabling Read Replication Fix: Use imperative form: ### Enable read replication
d1/best-practices/d1-complete-guide.mdx line 534 Heading uses -ing verb — Line adds ### Defining Relationships Fix: Use imperative form: ### Define relationships
d1/best-practices/d1-complete-guide.mdx line 22 Heading trailing punctuation — Line adds ## Is D1 Right for You? Fix: Remove trailing ?: ## Is D1 Right for You
d1/best-practices/d1-complete-guide.mdx line 51 Heading trailing punctuation — Line adds ## What Is D1? Fix: Remove trailing ?: ## What Is D1
d1/best-practices/d1-complete-guide.mdx line 125 Heading trailing punctuation — Line adds ### Step 1: Create a Database Fix: Remove trailing colon: ### Step 1 Create a Database
d1/best-practices/d1-complete-guide.mdx line 133 Heading trailing punctuation — Line adds ### Step 2: Create a Schema Fix: Remove trailing colon: ### Step 2 Create a Schema
d1/best-practices/d1-complete-guide.mdx line 147 Heading trailing punctuation — Line adds ### Step 3: Run the Schema Fix: Remove trailing colon: ### Step 3 Run the Schema
d1/best-practices/d1-complete-guide.mdx line 153 Heading trailing punctuation — Line adds ### Step 4: Bind the Database to a Worker Fix: Remove trailing colon: ### Step 4 Bind the Database to a Worker
d1/best-practices/d1-complete-guide.mdx line 168 Heading trailing punctuation — Line adds ### Step 5: Write Worker Code Fix: Remove trailing colon: ### Step 5 Write Worker Code
d1/best-practices/d1-complete-guide.mdx line 3 Escape angle brackets in MDX prose — Line adds unescaped > in prose: > A practical, opinionated guide for developers new to Cloudflare, Workers users ready for seamless storage, and AI agents building apps for hobbyists. Fix: Replace > with > or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 258 Escape angle brackets in MDX prose — Line adds unescaped > in prose: const statements = users.map(u => Fix: Replace > with > or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 286 Escape angle brackets in MDX prose — Line adds unescaped < in prose: return nextAttempt <= 3 && isRetryable; Fix: Replace < with &lt; or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 299 Escape angle brackets in MDX prose — Line adds unescaped > in prose: await new Promise(r => setTimeout(r, jitter)); Fix: Replace > with &gt; or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 319 Escape angle brackets in MDX prose — Line adds unescaped < in prose: SELECT id FROM old_logs WHERE created_at < ? Fix: Replace < with &lt; or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 324 Escape angle brackets in MDX prose — Line adds unescaped < in prose: if (result.meta.changes < CHUNK_SIZE) break; Fix: Replace < with &lt; or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 500 Escape angle brackets in MDX prose — Line adds unescaped > in prose: In the Cloudflare dashboard, go to \*\*D1\*\* > select your database > \*\*Settings\*\* > \*\*Enable Read Replication\*\*. Fix: Replace > with &gt; or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 700 Escape angle brackets in MDX prose — Line adds unescaped > in prose: async function runWithRetry<T>(fn: () => Promise<T>): Promise<T> { Fix: Replace > with &gt; or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 712 Escape angle brackets in MDX prose — Line adds unescaped > in prose: if (!retryable || attempt > 3) throw err; Fix: Replace > with &gt; or wrap the text in backticks.
d1/best-practices/d1-complete-guide.mdx line 713 Escape angle brackets in MDX prose — Line adds unescaped > in prose: await new Promise(r => setTimeout(r, Math.random() \* Math.min(50 \* 2 \*\* attempt, 2000))); Fix: Replace > with &gt; or wrap the text in backticks.
Suggestions (2)
File Issue
d1/best-practices/d1-complete-guide.mdx line 305 Non-descriptive link phrasing — Line adds See the [error list]... Fix: Use refer to [error list] instead
d1/best-practices/d1-complete-guide.mdx line 627 Etc. in body — Line adds etc. in a heading Fix: Replace with a complete list or and so on
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.

@ivoryibu ivoryibu marked this pull request as draft June 5, 2026 19:50
@ask-bonk ask-bonk Bot added the content:new Request for new/missing content label Jun 5, 2026
Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk Bot left a comment

Choose a reason for hiding this comment

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

This PR needs significant revision before merge. The new page is missing required frontmatter, uses full URLs for internal links and images, relies on bare code fences instead of mandatory components, and has multiple style guide violations.

CRITICAL

  • Missing frontmatter — Every docs page requires title, description, and pcx_content_type. The file opens with an H1 (# The Complete Guide...), which must be removed; the H1 is rendered from frontmatter.
  • Bare code fences — Workers JS/TS examples must use TypeScriptExample, Wrangler config must use WranglerConfig (with $today for compatibility_date), and package install commands must use PackageManagers.
  • Full URLs for internal links — Links to developers.cloudflare.com must be root-relative (/d1/.../). Images should use ~/assets/images/d1/... if they exist in the repo.
  • Missing component imports — All components used must be imported from ~/components.

HIGH

  • Emojis used as admonitions💡 Tip and ⚠️ Warning markers must be replaced with :::tip, :::caution, and :::note admonitions.
  • Contractions — "don't", "doesn't", "Can't" must be rewritten per the style guide ("do not", "does not", "Cannot").
  • Headings with punctuation/questions — "Is D1 Right for You?", "I Can't Connect...", etc. must use sentence-case noun/verb phrases without trailing punctuation.
  • LLM-filler phrases — Remove "seamless" from the opening blurb and "etc." from headings.
  • Hardcoded compatibility date — Use $today inside WranglerConfig.

MEDIUM

  • Misleading SQL example — The "Bad" example on line 219 is identical to the "Good" example apart from a comment. A full table scan and an indexed lookup look the same in SQL; the example should be clarified.
  • Unused variableoffset is declared in the chunk-deletion sample (line 315) but never used.
  • Limit claims — Values in the limits table (lines 449–458) should be cross-checked against the current D1 limits page for accuracy.

Out-of-scope note: Consider whether this content should be split into multiple pages (tutorial, troubleshooting, reference) or if linking to existing canonical pages more aggressively would reduce duplication.

Comment on lines +1 to +5
# The Complete Guide to Cloudflare D1

> A practical, opinionated guide for developers new to Cloudflare, Workers users ready for seamless storage, and AI agents building apps for hobbyists.

---
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.

Add required frontmatter and remove the H1. The page title renders from frontmatter.

Suggested change
# The Complete Guide to Cloudflare D1
> A practical, opinionated guide for developers new to Cloudflare, Workers users ready for seamless storage, and AI agents building apps for hobbyists.
---
---
title: The complete guide to Cloudflare D1
pcx_content_type: tutorial
description: A comprehensive tutorial for implementing Cloudflare D1 in production environments, covering architecture, optimization, schema migrations, and troubleshooting.
products:
- d1
---
import { PackageManagers, TypeScriptExample, WranglerConfig } from "~/components";
A practical, opinionated guide for developers new to Cloudflare, Workers users ready for storage, and AI agents building apps for hobbyists.


---

## Is D1 Right for You?
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.

Use a sentence-case noun phrase and remove trailing punctuation.

Suggested change
## Is D1 Right for You?
## Determine if D1 is right for you


### The Rule of Thumb

If you need a SQL database for a Cloudflare Worker or Pages project, and you don't need exotic PostgreSQL features like `JSONB` operators, `SERIAL` types, or stored procedures, **D1 is the path of least resistance**.
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.

Rewrite the contraction.

Suggested change
If you need a SQL database for a Cloudflare Worker or Pages project, and you don't need exotic PostgreSQL features like `JSONB` operators, `SERIAL` types, or stored procedures, **D1 is the path of least resistance**.
If you need a SQL database for a Cloudflare Worker or Pages project, and you do not need exotic PostgreSQL features like `JSONB` operators, `SERIAL` types, or stored procedures, **D1 is the path of least resistance**.

Comment on lines +119 to +122

```bash
npm install -g wrangler
npx wrangler login
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.

Use PackageManagers for install commands.

Suggested change
```bash
npm install -g wrangler
npx wrangler login
<PackageManagers type="install" pkg="wrangler" />
```sh
npx wrangler login

Comment on lines +158 to +167
name = "my-d1-app"
main = "src/index.js"
compatibility_date = "2024-01-01"

[[d1_databases]]
binding = "DB" # how you refer to it in code
database_name = "my-first-db"
database_id = "your-uuid-here"
```

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.

Use WranglerConfig and $today for the compatibility date.

Suggested change
name = "my-d1-app"
main = "src/index.js"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB" # how you refer to it in code
database_name = "my-first-db"
database_id = "your-uuid-here"
```
<WranglerConfig>
```toml
name = "my-d1-app"
main = "src/index.js"
compatibility_date = "$today"
[[d1_databases]]
binding = "DB" # how you refer to it in code
database_name = "my-first-db"
database_id = "your-uuid-here"
```

Comment on lines +172 to +199
```javascript
export default {
async fetch(request, env) {
const url = new URL(request.url);
const slug = url.pathname.slice(1);

if (request.method === "POST" && slug === "create") {
const body = await request.json();
await env.DB.prepare(
"INSERT INTO links (slug, url) VALUES (?, ?)"
).bind(body.slug, body.url).run();
return new Response("Created", { status: 201 });
}

const result = await env.DB.prepare(
"SELECT url FROM links WHERE slug = ?"
).bind(slug).first();

if (result) {
return Response.redirect(result.url, 302);
}

return new Response("Not found", { status: 404 });
}
};
```

Notice: `env.DB` is just there. No connection strings. No TLS certificates. No connection pools.
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.

Use TypeScriptExample for Workers code.

Suggested change
```javascript
export default {
async fetch(request, env) {
const url = new URL(request.url);
const slug = url.pathname.slice(1);
if (request.method === "POST" && slug === "create") {
const body = await request.json();
await env.DB.prepare(
"INSERT INTO links (slug, url) VALUES (?, ?)"
).bind(body.slug, body.url).run();
return new Response("Created", { status: 201 });
}
const result = await env.DB.prepare(
"SELECT url FROM links WHERE slug = ?"
).bind(slug).first();
if (result) {
return Response.redirect(result.url, 302);
}
return new Response("Not found", { status: 404 });
}
};
```
Notice: `env.DB` is just there. No connection strings. No TLS certificates. No connection pools.
Create `src/index.ts`:
<TypeScriptExample>
```ts
export default {
async fetch(request, env): Promise<Response> {
const url = new URL(request.url);
const slug = url.pathname.slice(1);
if (request.method === "POST" && slug === "create") {
const body = await request.json();
await env.DB.prepare(
"INSERT INTO links (slug, url) VALUES (?, ?)"
).bind(body.slug, body.url).run();
return new Response("Created", { status: 201 });
}
const result = await env.DB.prepare(
"SELECT url FROM links WHERE slug = ?"
).bind(slug).first();
if (result) {
return Response.redirect(result.url, 302);
}
return new Response("Not found", { status: 404 });
}
};
```

}
```

See the [error list](https://developers.cloudflare.com/d1/observability/debug-d1/#error-list) for exactly which errors are retryable.
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.

Use root-relative paths for internal links.

Suggested change
See the [error list](https://developers.cloudflare.com/d1/observability/debug-d1/#error-list) for exactly which errors are retryable.
See the [error list](/d1/observability/debug-d1/#error-list) for exactly which errors are retryable.


### 9. Use `db.withSession()` When Read Replication Is Enabled

Read replicas reduce latency for read-heavy apps with global users. Even if you don't enable read replication today, design your code to use the **Sessions API** from the start. This lets you toggle replication on later without changing Worker code.
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.

Rewrite the contraction.

Suggested change
Read replicas reduce latency for read-heavy apps with global users. Even if you don't enable read replication today, design your code to use the **Sessions API** from the start. This lets you toggle replication on later without changing Worker code.
Even if you do not enable read replication today, design your code to use the **Sessions API** from the start. This lets you toggle replication on later without changing Worker code.

- Do **not** use `PRAGMA foreign_keys = off`; it is silently ignored.
- Resolve all violations before the transaction commits.

### I Can't Connect from My Local GUI (TablePlus, DBeaver, etc.)
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.

Use a sentence-case noun phrase without punctuation or contractions.

Suggested change
### I Can't Connect from My Local GUI (TablePlus, DBeaver, etc.)
### Cannot connect from a local GUI (TablePlus, DBeaver)


### My Read Replica Data Is Stale

**Symptom:** A user submits a form, then reloads the page and doesn't see their update.
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.

Rewrite the contraction.

Suggested change
**Symptom:** A user submits a form, then reloads the page and doesn't see their update.
**Symptom:** A user submits a form, then reloads the page and does not see their update.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented Jun 5, 2026

I reviewed PR #31263 and posted a detailed review with 10 inline suggestions.

Summary of findings:

  • CRITICAL: The new d1-complete-guide.mdx page is missing required frontmatter (title, description, pcx_content_type), starts with an H1 (which must be rendered from frontmatter), and uses bare code fences where mandatory components are required (TypeScriptExample, WranglerConfig, PackageManagers). It also uses full developers.cloudflare.com URLs for internal links and images instead of root-relative paths.
  • HIGH: Multiple style guide violations including contractions (don't, doesn't, Can't), headings ending in punctuation or phrased as questions, inline emoji admonitions (💡, ⚠️) instead of :::tip/:::caution, LLM-filler phrases (seamless, etc.), and a hardcoded compatibility_date.
  • MEDIUM: A misleading SQL example (identical good/bad queries), an unused offset variable in the chunk-deletion sample, and limit claims that should be verified against current docs.

I also applied the content:new label to the PR.

github run

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 product:d1 D1: https://developers.cloudflare.com/d1/ size/l

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants