D1 (SQLite)
Cloudflare D1 is a serverless SQLite database distributed across Cloudflare's network. Void manages it for you, so there is no setup, no connection string, and no separate local database configuration during development.
When to Use D1
D1 is the default database for Void apps and a great choice when you want zero-config database access:
- Prototyping: start building immediately with no external database to provision
- Read-heavy apps: optimized for read workloads at the edge
- Small to medium scale: a good fit for apps that do not need advanced SQL features such as stored procedures or complex joins
- Simplicity: Void creates, migrates, and manages the D1 instance for you
For write-heavy workloads, complex queries, or connecting to existing infrastructure, see PostgreSQL.
Configuration
None. D1 is the default dialect, so you can start by defining your schema and querying.
Migrations & Prototyping
Void offers two workflows for applying schema changes.
Prototyping with push
During development, use void db push to apply your schema directly to the local D1 database. It does not create migration files.
void db pushThis diffs your Drizzle schema against the local database and applies the changes immediately. It's fast and ideal for iterating on your schema before committing to a migration.
Production migrations
When you're ready to ship, generate SQL migration files from your schema:
void db generateThis creates timestamped SQL files in db/migrations/ that capture the diff between your schema and the last generated migration.
To apply pending migrations locally:
void db migrateDeploy Workflow
When you run void deploy:
- The app is built
- Migration files are collected from
db/migrations/ - If the schema has drifted ahead of the migrations, you're prompted to generate and commit the new migrations
- Pending migrations run against the remote D1 database
- The new worker goes live
Deploys always go through migration files. push is only for local development.
Batch Operations
D1 supports batching multiple statements into a single round-trip:
import { db, eq } from 'void/db';
import { users, posts } from '@schema';
await db.batch([
db.delete(posts).where(eq(posts.userId, userId)),
db.delete(users).where(eq(users.id, userId)),
]);Alternative Query Layers
While Void's Drizzle integration is the recommended approach, you can use any library that accepts a D1 binding. Import env.DB from cloudflare:workers and pass it to your library:
Kysely
import { Kysely } from 'kysely';
import { D1Dialect } from 'kysely-d1';
import { env } from 'cloudflare:workers';
const db = new Kysely<Database>({ dialect: new D1Dialect({ database: env.DB }) });Raw D1
import { env } from 'cloudflare:workers';
const { results } = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).all();Void still handles binding inference and deployment regardless of which query layer you use.
⚠️ Meta framework limitation
Some frameworks, like Nuxt and SvelteKit, do not run in workerd during dev and therefore do not support directly importing from cloudflare:workers.