D1 foundations
Understand where D1 fits
Use relational structure and SQLite semantics without treating D1 as KV, object storage, or a process-local file.
D1 is Cloudflare’s relational database. Under the hood it’s SQLite, run as a managed service. You get tables, indexes, joins, constraints and transactions. Real SQL. And you never provision a server, open a port, or manage a connection pool.
If you know SQLite, you already know the query language. What changes is how you reach the database. A Worker talks to D1 through a binding, an object the platform injects into your code:
const user = await env.DB.prepare(
'select * from users where email = ?'
).bind(email).first()
There is no connection string and nothing to keep alive. You configure env.DB once in wrangler.jsonc, and it’s there on every request.
This matters more than it looks. D1 is not a .sqlite file your process owns. It’s a service with its own limits, its own transaction behavior, and its own migration workflow. Habits from embedded SQLite don’t transfer here. No long-lived open handles, no filesystem tricks, no “copy the file to back it up”.
Choose it for relational data
Pick D1 when your data is made of rows that reference each other. Users, notes, orders, settings. Anything that needs a query 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 whole argument for a relational database. With key-value lookups you would fetch everything and join by hand in JavaScript. It works for ten notes. It falls apart at ten thousand.
Know what it is not
Cloudflare has other storage products, and each one has its own job.
Store file bodies in R2. Images as blobs inside database rows waste both products. Use KV for read-heavy values that need no queries and can be a few seconds stale, like feature flags. Use 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 thing that needs coordination, Durable Objects.
We’ll build a notes application through this course, with users, notes and tags. Before the next lesson, sketch those three tables on paper. Find the primary keys, the relationships between them, and one query that only makes sense with a relational database.
Lesson completed