Create a D1 database with wrangler d1 create <db-name>; bind it to your Worker in wrangler.toml under [[d1_databases]] with binding name, database_name, and database_id
Manage migrations using the wrangler d1 migrations create <db-name> <migration-name> command, which creates a numbered SQL file in the migrations directory; apply with wrangler d1 migrations apply <db-name> for local dev or --remote for production
In the Worker, access the binding as env.DB (or whatever binding name you chose); execute queries with prepared statements: const stmt = env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId); const result = await stmt.first() or .all() or .run()
Use .batch() to execute multiple prepared statements in a single round trip: const results = await env.DB.batch([stmt1, stmt2, stmt3]); statements in a batch run sequentially in a transaction-like context but are not automatically atomic — wrap in explicit BEGIN/COMMIT if needed
Use .run() for INSERT/UPDATE/DELETE statements; the result object includes meta.changes (rows affected) and meta.last_row_id; use .first() for single-row SELECT and .all() for multi-row SELECT which returns a results array
Test locally with wrangler dev which creates a local SQLite-backed D1 instance; data is isolated from remote — use wrangler d1 execute <db-name> --remote --command 'SELECT ...' to query production
Known gotchas
D1 is built on SQLite and inherits its type affinity and locking model; SQLite only allows one write at a time (serialized writes), so high-concurrency write workloads will queue and may time out — D1 is best suited for read-heavy or moderate write workloads
Prepared statement parameters are positional (?) not named; the order of .bind() arguments must exactly match the order of ? placeholders or you will silently bind wrong values
Migrations are applied in numeric order by filename; if you delete or reorder migration files after applying them, subsequent wrangler d1 migrations apply calls will error or produce inconsistent state — treat migration files as append-only
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp