Search docs

Jump between documentation pages.

Use Cloudflare D1 with DaloyJS

Cloudflare D1 is a serverless SQLite-compatible database built into Cloudflare Workers. You access it through a Worker binding (no network driver, no auth token, no TCP) — making it the lowest-friction database for the Cloudflare adapter.

1. Provision via Wrangler

ts
pnpm add -D wrangler
pnpm dlx wrangler d1 create my-app-db

Add the returned binding to your wrangler.toml:

ts
[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "<id-from-create>"

2. Type the binding

ts
// src/types/env.d.ts
export interface Env {
  DB: D1Database;
}

3. Decorate the app per-request

D1 bindings live on env, not process.env, so decorate inside the Worker's fetch handler and call app.fetch(req) directly:

ts
import { z } from "zod";
import { App, secureHeaders } from "@daloyjs/core";
import type { Env } from "./types/env";

const app = new App();
app.use(secureHeaders());

const TodoSchema = z.object({ id: z.number(), title: z.string(), done: z.boolean() });

app.route({
  method: "GET",
  path: "/todos",
  operationId: "listTodos",
  responses: { 200: { description: "ok", body: z.array(TodoSchema) } },
  handler: async ({ state }) => {
    const { results } = await state.db
      .prepare("select id, title, done from todos")
      .all<{ id: number; title: string; done: number }>();
    return {
      status: 200,
      body: results.map((r) => ({ ...r, done: Boolean(r.done) })),
    };
  },
});

export default {
  async fetch(req: Request, env: Env) {
    app.decorate("db", env.DB);
    return app.fetch(req);
  },
};

4. Augment app state

ts
// src/types/state.d.ts
declare module "@daloyjs/core" {
  interface AppState {
    db: D1Database;
  }
}

Migrations

ts
pnpm dlx wrangler d1 migrations create my-app-db init
pnpm dlx wrangler d1 migrations apply my-app-db --local
pnpm dlx wrangler d1 migrations apply my-app-db --remote

With Drizzle ORM

ts
pnpm add drizzle-orm
// src/db/drizzle.ts
import { drizzle } from "drizzle-orm/d1";
import type { Env } from "../types/env";

export const createDb = (env: Env) => drizzle(env.DB);

With Prisma

Prisma supports D1 via the D1 Driver Adapter. Construct the adapter inside the Worker handler since it needs the runtime binding.

Limitations to know

  • D1 only runs in Cloudflare Workers — no Node.js, Lambda, or Edge runtime support.
  • Local development uses wrangler dev with a local SQLite file; behavior is close but not identical to production.
  • For multi-runtime portability, prefer Turso (libSQL) instead.

See also Turso, Neon, and the database hosting overview.