Overview Install Files SecuritySummary | Type-safe ORM for Cloudflare D1 databases using Drizzle. Use when: building D1 database schemas, writing type-safe SQL queries, managing migrations with Drizzle Kit, defining table relations, implementing prepared statements, using D1 batch API, or encountering D1_ERROR, transaction errors, foreign key constraint failures, or schema inference issues.
Drizzle ORM for Cloudflare D1
Status : Production Ready ✅
Last Updated : 2025-12-14
Latest Version : [email protected] , [email protected]
Dependencies : cloudflare-d1, cloudflare-worker-base
Quick Start (10 Minutes)
1. Install Drizzle
bun add drizzle-orm drizzle-kit
2. Configure Drizzle Kit
Create drizzle.config.ts:
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './src/db/schema.ts',
out: './migrations',
dialect: 'sqlite', // MANDATORY since drizzle-kit 0.21 (D1 = sqlite)
driver: 'd1-http', // D1 HTTP driver for remote migrations/Studio
dbCredentials: { // MANDATORY: drizzle-kit 0.30+ tightened zod validation
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
databaseId: process.env.CLOUDFLARE_DATABASE_ID!,
token: process.env.CLOUDFLARE_D1_TOKEN!,
},
});
drizzle-kit 0.30/0.31 note : dialect and dbCredentials are now strictly
validated. A config that omits dialect or uses the old connectionString/
uri keys will fail validation. For D1 use dialect: 'sqlite' +
driver: 'd1-http' with accountId/databaseId/token (or wrangler-based
credentials). The runtime migrate() signature in drizzle-orm/<driver>/migrator
is unchanged from 0.36 → 0.45 (it changes only in 1.0-beta, which is out of
scope for ^0.45).
3. Define Schema
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
import { relations } from 'drizzle-orm';
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
email: text('email').notNull().unique(),
name: text('name').notNull(),
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
});
export const posts = sqliteTable('posts', {
id: integer('id').primaryKey({ autoIncrement: true }),
title: text('title').notNull(),
content: text('content').notNull(),
authorId: integer('author_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
});
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
4. Generate & Apply Migrations bunx drizzle-kit generate # Generate SQL
bunx wrangler d1 migrations apply my-database --local # Apply local
bunx wrangler d1 migrations apply my-database --remote # Apply prod
5. Query in Worker import { drizzle } from 'drizzle-orm/d1';
import { users } from './db/schema';
import { eq } from 'drizzle-orm';
export default {
async fetch(request: Request, env: { DB: D1Database }): Promise<Response> {
const db = drizzle(env.DB);
const allUsers = await db.select().from(users).all();
return Response.json(allUsers);
},
};
Critical Rules
Always Do Rule Why Use drizzle-kit generate for migrations Never write SQL manually Test migrations locally first --local before --remoteUse .get() for single results Returns first row or undefined Use db.batch() for transactions D1 doesn't support SQL BEGIN/COMMIT Use integer with mode: 'timestamp' for dates D1 has no native date type Use .$defaultFn() for dynamic defaults Not .default() for functions
Never Do Rule Why Use SQL BEGIN TRANSACTION D1 requires batch API (Error #1) Mix drizzle-kit migrate and wrangler apply Use Wrangler only Use drizzle-kit push for production Use generate + apply Commit credentials in drizzle.config.ts Use env vars Use .default() for function calls Use .$defaultFn() instead
Top 5 Critical Errors # Error Solution 1 D1_ERROR: Cannot use BEGIN TRANSACTIONUse db.batch([...]) instead of db.transaction() 2 FOREIGN KEY constraint failedDefine cascading: .references(() => users.id, { onDelete: 'cascade' }) 3 env.DB is undefinedEnsure binding in wrangler.jsonc matches env.DB 4 No such module "wrangler"Use import { drizzle } from 'drizzle-orm/d1' 5 Type instantiation excessively deepUse InferSelectModel<typeof users> for explicit types
See : references/error-catalog.md for all 12 errors with complete solutions.
Common Patterns Summary Pattern Use Case Template CRUD Operations Basic database operations templates/basic-queries.tsRelations & Joins Nested queries, manual joins templates/relations-queries.tsBatch Operations Transactions (D1 batch API) templates/transactions.tsSchema Design Naming, indexes, soft deletes references/schema-patterns.md
Configuration Summary File Purpose Template drizzle.config.tsDrizzle Kit configuration templates/drizzle.config.tswrangler.jsoncD1 binding setup references/wrangler-setup.mdpackage.jsonnpm scripts for migrations templates/package.json
{
"db:generate": "drizzle-kit generate",
"db:migrate:local": "wrangler d1 migrations apply my-database --local",
"db:migrate:remote": "wrangler d1 migrations apply my-database --remote"
}
Migration Workflow Step Command Notes 1. Edit schema Edit src/db/schema.ts Make changes 2. Generate npm run db:generateCreates SQL migration 3. Test local npm run db:migrate:localVerify locally 4. Deploy code npm run deployPush to Cloudflare 5. Apply prod npm run db:migrate:remoteApply migration
See : references/migration-workflow.md for complete workflow.
TypeScript Type Inference import { InferSelectModel, InferInsertModel } from 'drizzle-orm';
import { users } from './db/schema';
export type User = InferSelectModel<typeof users>;
export type NewUser = InferInsertModel<typeof users>;
When to Load References Reference Load When... references/error-catalog.mdDebugging D1 errors, transaction failures, binding issues references/schema-patterns.mdDesigning schemas, naming conventions, indexes, soft deletes references/migration-workflow.mdSetting up or troubleshooting migrations references/query-builder-api.mdComplex queries, operators, joins syntax references/wrangler-setup.mdConfiguring wrangler.jsonc for D1 references/common-errors.mdQuick error lookup
Bundled Resources Templates : basic-schema.ts, basic-queries.ts, transactions.ts, relations-queries.ts, prepared-statements.ts, drizzle.config.ts, package.json
References : error-catalog.md, schema-patterns.md, migration-workflow.md, query-builder-api.md, wrangler-setup.md, common-errors.md, links-to-official-docs.md
Dependencies {
"dependencies": {
"drizzle-orm": "^0.45.2"
},
"devDependencies": {
"drizzle-kit": "^0.31.10"
}
}
Secure Installation When installing Drizzle ORM and D1 driver packages, follow supply chain security best practices:
Block post-install scripts — npm config set ignore-scripts true (or Bun: disabled by default)
Cooldown period — Wait 7 days for new package versions to be vetted by the community
Audit before installing — Run socket package score npm <pkg> or use socket npm install <pkg> to check packages
Load the dependency-upgrade skill for full security configuration including Socket CLI integration, cooldown setup, lockfile validation, and CI enforcement.
Official Documentation
Token Savings : ~65% (comprehensive patterns in references)
Error Prevention : 100% (all 12 documented issues)
Ready for production! ✅