Database
For the complete documentation index, see llms.txt. Prefer markdown by appending .md to documentation URLs or sending Accept: text/markdown.

Overview

Use the Edge database client, understand local and remote D1 state, and choose the right command for migrations and development seeds.

Your application database is the DB binding. The app uses Drizzle's D1 adapter over Cloudflare's SQLite database. It's simpler and there is no database connection URL to configure, it just works.

Why D1 and Drizzle?

D1 provides managed SQL through a Worker binding, with no database server or connection pool to operate. Drizzle adds typed queries and reviewable SQL migrations while keeping the underlying relational model visible. Together, they fit the kit's TypeScript application and Cloudflare deployment.

Database model

Cloudflare D1 is a managed SQL database built on SQLite. It stores structured application records, such as customer accounts, subscriptions, and the resources your product adds. Relationships connect those records, while constraints help preserve valid data.

Drizzle gives your TypeScript code a typed view of the database. You describe tables in a schema, review generated SQL migrations, and use queries to read or change records through the existing client.

ConceptRole
SchemaThe tables, columns, relationships, and constraints your code expects
MigrationA reviewed change applied to an existing database
QueryA read or write performed by an application feature
SeedDevelopment data for exercising the product locally

Changing a schema definition alone does not change a running database. Migrations bring the database into agreement with that definition, while queries operate on the state currently deployed.

Keep file contents in R2 storage and their ownership or descriptive records in D1. Use KV for reusable values that tolerate its consistency model, rather than replacing relational product data with a cache.

Usage

In server code, import the existing client and use it to query the database:

import { eq } from "drizzle-orm";

import { db } from "@/db";
import { user } from "@/db/schema";

export async function findUser(userId: string) {
  const [record] = await db.select().from(user).where(eq(user.id, userId));
  return record ?? null;
}

Call database helpers through a protected server function. Resolve the user ID from the session before filtering private records.

Local vs production

The Cloudflare Vite plugin simulates DB locally, storing state under .wrangler/state. Your deployed Worker uses the database ID in wrangler.jsonc. Applying a migration locally does not change remote D1, and production data is not automatically copied into your development replica.

While pnpm dev runs, open Cloudflare's local SQL Studio to browse D1 tables, inspect rows, and run queries against this replica.

TaskCommandTarget
Apply migrations and seed a dev userpnpm db:setupLocal replica
Apply pending migrations onlypnpm db:migrate --localLocal replica
Seed the development userpnpm db:seedLocal replica
Regenerate auth schema and generate SQLpnpm db:generateSchema files, not database data
Build, migrate, and deploypnpm deployRemote database, then Worker

The seed script uses getPlatformProxy with remoteBindings: false. It does not seed production. The development user is verified and gets a password account, so you can sign in without waiting for email. SEED_EMAIL and SEED_PASSWORD control its credentials.

Running the seed again updates the existing user's profile, but does not replace an existing credential account's password. Changing SEED_PASSWORD is not a password reset. Use the app's password reset flow or recreate your disposable local user when testing different credentials.

Generated auth tables

pnpm db:generate overwrites src/db/schema/auth.ts with Better Auth's schema before generating SQL. Keep application tables in other files under src/db/schema/ and export them from src/db/schema/index.ts. Follow schema changes before adding your first table.

How is this guide?

Last updated on

On this page

Ship globally on the edge. In minutes.Try Edge Kit