setup-d1-cloudflare-worker-with-drizzle ×

Setting up D1 Database with Drizzle in a Hono Cloudflare Worker App

BY CREATED Jan 12, 2025 UPDATED Apr 18, 2026 ~4 min read

This guide covers configuring a D1 database using Drizzle in a Hono app deployed using Cloudflare Workers.

To create a cloudflare worker app, we just need to run below command.

bash
pnpm create hono@latest
# Ensure that you select "Cloudflare Workers" as the deployment target

in the wrangler.jsonc , add D1 database config, ensure that migrations_dir set to folder called migrations. This will be the migration file created by drizzle later.

jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-hono-app",
  "main": "src/index.ts",
  "compatibility_date": "2025-11-01",
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "Hono DB",
      "database_id": "abcdabcd-abcd-abcd-abcd-abcdabcdabcd",
      "migrations_dir": "migrations"
    }
  ]
}

Note: The database_name and database_id will come from your Cloudflare dashboard later. For local development, you can use any values for now.

Note: wrangler.jsonc is the current default when scaffolding a new worker. If you have an older project using wrangler.toml, it still works — the equivalent TOML block is [[d1_databases]] with the same keys.

Update Bindings#

create the typescript type file for the Cloudflare binding.

shell
wrangler types src/worker.d.ts

this creates a typescript type file called worker.d.ts. this file will contain the Cloudflare binding as we defined wrangler.toml file.

ts
// Generated by Wrangler by running `wrangler types src/worker.d.ts`  
  
interface Env {  
    DB: D1Database;  
}

To integrate this into our Hono app, we create a type file as per below

ts
// src/types.d.ts
import type {RequestIdVariables} from "hono/request-id";  
import {Hono} from "hono";  
  
export type App = {  
    Bindings: Env,  
    Variables: RequestIdVariables  
}  
  
export type AppOpenAPi = Hono<App>;

Under src/index.ts, add a basic Hono app.

ts
import { Hono } from 'hono'  
import {App} from "./types";  
  
const app = new Hono<App>()  
  
app.get('/', (c) => {  
  return c.text('Hello World')  
})  
  
export default app

Drizzle Integration#

To add drizzle into the created project, we need to install its dependencies

bash
pnpm add drizzle-orm  
pnpm add -D drizzle-kit

Then we need to add a drizzle config file

ts
//drizzle.config.ts
import { defineConfig } from 'drizzle-kit';  
  
export default defineConfig({  
    out: './migrations',  
    schema: './src/db/schema.ts',  
    dialect: 'sqlite',  
});

This config file will only be used for Db migration.

Now we need to add Drizzle schema that will be used to generate the Db migration script

ts
//src/db/schema.ts
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";  
  
export const users = sqliteTable("users", {  
    id: int().primaryKey({ autoIncrement: true }),  
    name: text().notNull(),  
    age: int().notNull(),  
    email: text().notNull().unique(),  
});

to generate a migration, we need to run below command

shell
pnpm drizzle-kit generate

Drizzle will create a migration code under migrations folder

to push this migration to the database, we need to run below command

shell
wrangler d1 migrations apply "Hono DB" --local
# `Hono DB` is the value under `database_name` that we defined in `wrangler.jsonc`

The --local flag applies the migration against the local Miniflare SQLite file (under .wrangler/state/). It is the default when the flag is omitted, but passing it explicitly avoids confusion with the remote variant below — and means you never accidentally run a migration against production.

Integrate with Hono#

Now we can update our Hono app to access the users table

ts
//src/index.ts

import { Hono } from 'hono'  
import {App} from "./types";  
import { drizzle } from 'drizzle-orm/d1';  
import {users} from "./db/schema";  
  
const app = new Hono<App>()  
  
app.get('/', (c) => {  
  return c.text(c.env.my_secret)  
})  
  
app.get('/users', async (c) => {  
  const db = drizzle(c.env.DB);  
  const result = await db.select().from(users).all()  
  return c.json(result)  
})  
  
app.post('/users', async (c) => {  
  const jsonData = await c.req.json();  
  const db = drizzle(c.env.DB);  
  const result = await db.insert(users).values(jsonData)  
  
  return c.json(result)  
})  
  
  
export default app

Drizzle Studio#

Drizzle Studio is a feature provided by Drizzle to make working with drizzle become much easier. this feature usually use a lot during development. However, the we cannot use the current drizzle config because that required us to point to local sqlite file which we dont have (kinda). so we should create a new drizzle config file named drizzle-dev.config.ts

ts
import type { Config } from "drizzle-kit";  
  
const config: Config = {  
    out: './migrations',  
    schema: './src/db/schema.ts',  
    dialect: 'sqlite',  
    dbCredentials: {  
        url: "",
    },  
};  
  
export default config;

Find your local SQLite file path:

  • Look under .wrangler/state/v3/d1/miniflare-D1DatabaseObject
  • Update the url in the config with the full path, e.g.: "file:.wrangler/state/v3/d1/miniflare-D1DatabaseObject/3b553bae5256c5b08dde7a22ca1f24582e24203302bf1da3989e3550b9dc0b07.sqlite"

To run Drizzle studio

shell
pnpm drizzle-kit studio --config=drizzle-dev.config.ts

Push to cloudflare#

first you need to ensure the database is created in cloudflare, to create new D1 db, just run below command

shell
npx wrangler d1 create "Hono DB"

this command will return you a response similar to this

✅ Successfully created DB 'Hono DB App' in region WNAM
Created your new D1 database.

[[d1_databases]]
binding = "DB"
database_name = "Hono DB"
database_id = "abcdabcd-abcd-abcd-abcd-abcdabcdabcd"

we can use this information to update our wrangler.jsonc file

Then we can run below command to apply migrations to the remote (production) database

wrangler d1 migrations apply "Hono DB" --remote

Unlike --local, --remote hits the actual D1 database in your Cloudflare account. Double-check the database name before running.

References#

https://developers.cloudflare.com/workers/wrangler/commands/#d1-migrations-apply