Build type-safe D1 databases with Drizzle ORM. Includes schema definition, migrations with Drizzle Kit, relations, and D1 batch API patterns. Prevents 18 errors including SQL BEGIN failures, cascade data loss, 100-parameter limits, and foreign key issues. Use when: defining D1 schemas, managing migrations, bulk inserts, or troubleshooting D1_ERROR, BEGIN TRANSACTION, foreign keys, "too many SQL variables".
View on GitHubSelect agents to install to:
npx add-skill https://github.com/jezweb/claude-skills/blob/main/skills/drizzle-orm-d1/SKILL.md -a claude-code --skill drizzle-orm-d1Installation paths:
.claude/skills/drizzle-orm-d1/# Drizzle ORM for Cloudflare D1
**Status**: Production Ready ✅
**Last Updated**: 2026-01-20
**Latest Version**: drizzle-orm@0.45.1, drizzle-kit@0.31.8, better-sqlite3@12.5.0
**Dependencies**: cloudflare-d1, cloudflare-worker-base
---
## Quick Start (5 Minutes)
```bash
# 1. Install
npm install drizzle-orm
npm install -D drizzle-kit
# 2. Configure drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './src/db/schema.ts',
out: './migrations',
dialect: 'sqlite',
driver: 'd1-http',
dbCredentials: {
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
databaseId: process.env.CLOUDFLARE_DATABASE_ID!,
token: process.env.CLOUDFLARE_D1_TOKEN!,
},
});
# 3. Configure wrangler.jsonc
{
"d1_databases": [{
"binding": "DB",
"database_name": "my-database",
"database_id": "your-database-id",
"migrations_dir": "./migrations" // CRITICAL: Points to Drizzle migrations
}]
}
# 4. Define schema (src/db/schema.ts)
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
email: text('email').notNull().unique(),
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
});
# 5. Generate & apply migrations
npx drizzle-kit generate
npx wrangler d1 migrations apply my-database --local # Test first
npx wrangler d1 migrations apply my-database --remote # Then production
# 6. Query in Worker
import { drizzle } from 'drizzle-orm/d1';
import { users } from './db/schema';
const db = drizzle(env.DB);
const allUsers = await db.select().from(users).all();
```
---
## D1-Specific Critical Rules
✅ **Use `db.batch()` for transactions** - D1 doesn't support SQL BEGIN/COMMIT (see Issue #1)
✅ **Test migrations locally first** - Always `--local` before `--remote`
✅ **Use `integer` with `mode: 'timestamp'` for dates** - D1 has no native date type
✅ **Use `.$defaultFn()` f