Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
jezweb avatar

D1 Migration

  • 982 installs
  • 946 repo stars
  • Updated July 2, 2026
  • jezweb/claude-skills

d1-migration is a Claude Code skill that walks through Cloudflare D1 database migrations with Drizzle ORM for developers who need to generate, inspect, apply, and recover failed `.sql` migration files safely.

About

d1-migration is a jezweb Claude Code skill (claude-code-only) for Cloudflare D1 migrations powered by Drizzle ORM. The standard flow runs `pnpm db:generate` to create a new `.sql` file under `drizzle/`, then insists developers read the generated SQL before applying because Drizzle can emit destructive or surprising statements. It covers applying migrations to local and remote D1 instances, fixing stuck migrations, and handling partial failures. Developers reach for d1-migration when standing up D1 schemas, shipping schema changes on Workers, or debugging migration errors instead of improvising wrangler and Drizzle commands from memory.

  • Generates Drizzle migrations with pnpm db:generate
  • Critical SQL inspection step that catches destructive table-recreation patterns
  • Handles local and remote D1 application with partial-failure recovery
  • Fixes stuck migrations and schema gotchas before they reach production
  • 4-step guided workflow: generate → inspect → apply → recover

D1 Migration by the numbers

  • 982 all-time installs (skills.sh)
  • +24 installs in the week ending Jul 29, 2026 (Skillselion tracking)
  • Ranked #89 of 911 Databases skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Jul 31, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jezweb/claude-skills --skill d1-migration

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs982
repo stars946
Security audit3 / 3 scanners passed
Last updatedJuly 2, 2026
Repositoryjezweb/claude-skills

How do you safely run Cloudflare D1 Drizzle migrations?

Safely generate, inspect, apply, and recover from Cloudflare D1 database migrations using Drizzle ORM.

Who is it for?

Developers on Cloudflare Workers using Drizzle ORM who need a guarded generate-inspect-apply migration workflow for D1.

Skip if: Developers on PostgreSQL or PlanetScale without Cloudflare D1, or teams not using Drizzle for schema management.

When should I use this skill?

The user runs D1 migrations, sees Drizzle SQL errors, or asks to fix stuck or partial Cloudflare D1 migration failures.

What you get

Reviewed `.sql` migration files applied to local and remote D1 databases with documented recovery steps for failures.

  • Drizzle `.sql` migration files
  • Applied local and remote D1 schema state

Files

SKILL.mdMarkdownGitHub ↗

D1 Migration Workflow

Guided workflow for Cloudflare D1 database migrations using Drizzle ORM.

Standard Migration Flow

1. Generate Migration

pnpm db:generate

This creates a new .sql file in drizzle/ (or your configured migrations directory).

2. Inspect the SQL (CRITICAL)

Always read the generated SQL before applying. Drizzle sometimes generates destructive migrations for simple schema changes.

Red Flag: Table Recreation

If you see this pattern, the migration will likely fail:

CREATE TABLE `my_table_new` (...);
INSERT INTO `my_table_new` SELECT ..., `new_column`, ... FROM `my_table`;
--                                      ^^^ This column doesn't exist in old table!
DROP TABLE `my_table`;
ALTER TABLE `my_table_new` RENAME TO `my_table`;

Cause: Changing a column's default value in Drizzle schema triggers full table recreation. The INSERT SELECT references the new column from the old table.

Fix: If you're only adding new columns (no type/constraint changes on existing columns), simplify to:

ALTER TABLE `my_table` ADD COLUMN `new_column` TEXT DEFAULT 'value';

Edit the .sql file directly before applying.

3. Apply to Local

pnpm db:migrate:local
# or: npx wrangler d1 migrations apply DB_NAME --local

4. Apply to Remote

pnpm db:migrate:remote
# or: npx wrangler d1 migrations apply DB_NAME --remote

Always apply to BOTH local and remote before testing. Local-only migrations cause confusing "works locally, breaks in production" issues.

5. Verify

# Check local
npx wrangler d1 execute DB_NAME --local --command "PRAGMA table_info(my_table)"

# Check remote
npx wrangler d1 execute DB_NAME --remote --command "PRAGMA table_info(my_table)"

Fixing Stuck Migrations

When a migration partially applied (e.g. column was added but migration wasn't recorded), wrangler retries it and fails on the duplicate column.

Symptoms: pnpm db:migrate errors on a migration that looks like it should be done. PRAGMA table_info shows the column exists.

Diagnosis

# 1. Verify the column/table exists
npx wrangler d1 execute DB_NAME --remote \
  --command "PRAGMA table_info(my_table)"

# 2. Check what migrations are recorded
npx wrangler d1 execute DB_NAME --remote \
  --command "SELECT * FROM d1_migrations ORDER BY id"

Fix

# 3. Manually record the stuck migration
npx wrangler d1 execute DB_NAME --remote \
  --command "INSERT INTO d1_migrations (name, applied_at) VALUES ('0013_my_migration.sql', datetime('now'))"

# 4. Run remaining migrations normally
pnpm db:migrate

Prevention

  • CREATE TABLE IF NOT EXISTS — safe to re-run
  • ALTER TABLE ADD COLUMN — SQLite has no IF NOT EXISTS variant; check column existence first or use try/catch in application code
  • Always inspect generated SQL before applying (Step 2 above)

Bulk Insert Batching

D1's parameter limit causes silent failures with large multi-row INSERTs. Batch into chunks:

const BATCH_SIZE = 10;
for (let i = 0; i < allRows.length; i += BATCH_SIZE) {
  const batch = allRows.slice(i, i + BATCH_SIZE);
  await db.insert(myTable).values(batch);
}

Why: D1 fails when rows x columns exceeds ~100-150 parameters.

Column Naming

ContextConventionExample
Drizzle schemacamelCasecaseNumber: text('case_number')
Raw SQL queriessnake_caseUPDATE cases SET case_number = ?
API responsesMatch SQL aliasesSELECT case_number FROM cases

New Project Setup

When creating a D1 database for a new project, follow this order:

1. Deploy Worker firstnpm run build && npx wrangler deploy 2. Create D1 databasenpx wrangler d1 create project-name-db 3. Copy database_id to wrangler.jsonc d1_databases binding 4. Redeploynpx wrangler deploy 5. Run migrations — apply to both local and remote

Related skills

How it compares

Pick d1-migration over generic SQL migration guides when the stack is Cloudflare D1 plus Drizzle on Workers.

FAQ

What command generates D1 migrations in d1-migration?

d1-migration starts with `pnpm db:generate`, which creates a new `.sql` file in the configured `drizzle/` migrations directory for review before any apply step.

Why must developers read SQL before applying?

d1-migration requires inspecting Drizzle-generated SQL because Drizzle can emit destructive or unexpected statements that should be caught before local or remote D1 apply.

Is D1 Migration safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Databasesbackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.