Skip to main content
Cloudflare D1 is a serverless SQLite database that runs at the edge alongside your Worker. Blaze makes it available on req.env.DB in every handler the moment you add the binding to your Env type — no connection pooling, no client initialization, just prepare → bind → execute.

Configure the binding

1

Add the database to wrangler.toml

wrangler.toml
2

Define the Env type

src/types/env.ts
3

Pass Env to createApp

src/index.ts

Querying rows

D1 uses a prepared-statement API. Call .prepare(sql) to create a statement, .bind(...values) to safely interpolate parameters, then either .first() for a single row or .all() for a full result set. The example below implements a paginated user listing using page and limit query parameters:

Inserting and updating

Use .run() for statements that modify data. When you append RETURNING id to an INSERT, switch to .first() to retrieve the generated ID in a single round-trip.

Batch statements

req.env.DB.batch([...]) executes multiple prepared statements in a single round-trip and treats them as an atomic unit — if one statement fails, none of the changes are committed. Use batching whenever you need to insert or update multiple related rows together.

Handling no results

.first() returns null when no row matches. Always check for null before accessing row properties and return a 404 so your client receives a meaningful response.

TypeScript row types

Pass your row shape as a generic argument to .first<T>() or .all<T>(). D1 returns plain objects, so the generic is a cast — align it with your actual schema to avoid surprises.
D1 is eventually consistent for read replicas in multi-region deployments. Writes go to the primary region first and propagate to read replicas within seconds. If your application needs immediate read-your-write consistency after an insert or update, direct that follow-up read to the primary by using wrangler d1 migrations and testing locally with --local to verify behavior before deploying.