D1 foundations

Understand where D1 fits

Use relational structure and SQLite semantics without treating D1 as KV, object storage, or a process-local file.

8 minute lesson

~~~

D1 is Cloudflare’s managed relational database built on SQLite. You get tables, indexes, joins, constraints, and transactions — real SQL, without provisioning a server, opening a network port, or managing a connection pool.

If you know SQLite, the query language is already familiar. What changes is the access model. A Worker talks to D1 through a binding rather than opening a local file:

const user = await env.DB.prepare(
  'select * from users where email = ?'
).bind(email).first()

There is no connection string and nothing to keep alive. env.DB is injected by the platform, configured once in wrangler.jsonc.

That distinction matters more than it looks. D1 is not a .sqlite file your process owns. It is a managed service with its own limits, its own transaction behavior, and a migration workflow. Habits from embedded SQLite — long-lived open handles, filesystem tricks, “just copy the file to back it up” — do not transfer.

Choose it for relational data

Choose D1 when rows, relationships, constraints, transactions, and SQL queries match the data. Users, notes, orders, settings: entities that reference each other and need queries like “the ten most recent notes by this user, with their tags.”

select notes.title, group_concat(tags.name) as tags
from notes
join note_tags on note_tags.note_id = notes.id
join tags on tags.id = note_tags.tag_id
where notes.user_id = ?
group by notes.id
order by notes.created_at desc
limit 10;

That query is the argument for relational storage. Doing the same with key-value lookups means fetching everything and joining by hand in JavaScript.

Know what it is not

Each neighbor product keeps its own job. Choose R2 for file bodies — storing images as blobs in database rows wastes both products. Choose KV for read-heavy, eventually consistent values with no query needs, like feature flags. Choose Durable Objects when one entity needs serialized coordination, like a counter that must be exact under concurrency.

My rule of thumb: a key and a value, KV. Entities and relationships, D1. Files, R2. One hot coordinated thing, Durable Objects.

Now model a notes application with users, notes, and tags. Identify the primary keys, the relationships between the three tables, and one query that makes relational storage useful.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →