Skip to content
drizzle-orm-d1 logo

Drizzle ORM for Cloudflare D1

drizzle-orm-d1

| 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, for...

secondsky/claude-skills0installs226stars

SKILL.md

Full skill instructions

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',
  driver: 'd1-http',
  dbCredentials: {
    accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
    databaseId: process.env.CLOUDFLARE_DATABASE_ID!,
    token: process.env.CLOUDFLARE_D1_TOKEN!,
  },
});

3. Define Schema

Create src/​db/​schema.ts:

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

RuleWhy
Use drizzle-kit generate for migrationsNever write SQL manually
Test migrations locally first--local before --remote
Use .get() for single resultsReturns first row or undefined
Use db.batch() for transactionsD1 doesn't support SQL BEGIN/​COMMIT
Use integer with mode: 'timestamp' for datesD1 has no native date type
Use .$defaultFn() for dynamic defaultsNot .default() for functions

Never Do

RuleWhy
Use SQL BEGIN TRANSACTIOND1 requires batch API (Error #1)
Mix drizzle-kit migrate and wrangler applyUse Wrangler only
Use drizzle-kit push for productionUse generate + apply
Commit credentials in drizzle.config.tsUse env vars
Use .default() for function callsUse .$defaultFn() instead

Top 5 Critical Errors

#ErrorSolution
1D1_ERROR: Cannot use BEGIN TRANSACTIONUse db.batch([...]) instead of db.transaction()
2FOREIGN KEY constraint failedDefine cascading: .references(() => users.id, { onDelete: 'cascade' })
3env.DB is undefinedEnsure binding in wrangler.jsonc matches env.DB
4No such module "wrangler"Use import { drizzle } from 'drizzle-orm/​d1'
5Type instantiation excessively deepUse InferSelectModel<typeof users> for explicit types

See: references/​error-catalog.md for all 12 errors with complete solutions.


Common Patterns Summary

PatternUse CaseTemplate
CRUD OperationsBasic database operationstemplates/​basic-queries.ts
Relations & JoinsNested queries, manual joinstemplates/​relations-queries.ts
Batch OperationsTransactions (D1 batch API)templates/​transactions.ts
Schema DesignNaming, indexes, soft deletesreferences/​schema-patterns.md

Configuration Summary

FilePurposeTemplate
drizzle.config.tsDrizzle Kit configurationtemplates/​drizzle.config.ts
wrangler.jsoncD1 binding setupreferences/​wrangler-setup.md
package.jsonnpm scripts for migrationstemplates/​package.json

npm scripts:

{
  "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

StepCommandNotes
1. Edit schemaEdit src/​db/​schema.tsMake changes
2. Generatenpm run db:generateCreates SQL migration
3. Test localnpm run db:migrate:localVerify locally
4. Deploy codenpm run deployPush to Cloudflare
5. Apply prodnpm 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

ReferenceLoad 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.44.7"
  },
  "devDependencies": {
    "drizzle-kit": "^0.31.7"
  }
}

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! ✅