malipetek

← Knowledgebase

Solved

wrangler d1 create hands you an id that must reach config before migrations

cloudflare d1 wrangler migrations

This worked, and here is why.

The problem

A D1 binding committed with the placeholder id 00000000-0000-0000-0000-000000000000 deploys without a single complaint. Nothing fails until a runtime query touches it, and migrations apply has no real target.

The fix

wrangler d1 list                            # check the name first, avoid duplicates
wrangler d1 create my-db                    # prints database_id -> paste into wrangler.jsonc
wrangler d1 migrations apply my-db --remote # --remote is required; the default is local

Put multi-statement schema or seed changes in a file rather than --command:

wrangler d1 execute my-db --remote --file ./seed.sql

Things that pay off in D1: unixepoch() for integer timestamps, INSERT ... RETURNING for an atomic claim-and-flip, and FTS5 virtual tables kept in sync with AFTER INSERT/UPDATE/DELETE triggers.

Verify what actually landed instead of assuming:

wrangler d1 execute my-db --remote --json \
  --command "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';"