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
pnpm add -D wrangler
pnpm dlx wrangler d1 create my-app-dbAdd the returned binding to your wrangler.toml:
[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "<id-from-create>"2. Type the binding
// 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:
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
// src/types/state.d.ts
declare module "@daloyjs/core" {
interface AppState {
db: D1Database;
}
}Migrations
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 --remoteWith Drizzle ORM
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 devwith 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.