Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/d1/configuration.md
1# D1 Configuration23## wrangler.jsonc Setup45```jsonc6{7"name": "your-worker-name",8"main": "src/index.ts",9"compatibility_date": "2025-01-01", // Use current date for new projects10"d1_databases": [11{12"binding": "DB", // Env variable name13"database_name": "your-db-name", // Human-readable name14"database_id": "your-database-id", // UUID from dashboard/CLI15"migrations_dir": "migrations" // Optional: default is "migrations"16},17// Read replica (paid plans only)18{19"binding": "DB_REPLICA",20"database_name": "your-db-name",21"database_id": "your-database-id" // Same ID, different binding22},23// Multiple databases24{25"binding": "ANALYTICS_DB",26"database_name": "analytics-db",27"database_id": "yyy-yyy-yyy"28}29]30}31```3233## TypeScript Types3435```typescript36interface Env { DB: D1Database; ANALYTICS_DB?: D1Database; }3738export default {39async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {40const result = await env.DB.prepare('SELECT * FROM users').all();41return Response.json(result.results);42}43}44```4546## Migrations4748File structure: `migrations/0001_initial_schema.sql`, `0002_add_posts.sql`, etc.4950### Example Migration5152```sql53-- migrations/0001_initial_schema.sql54CREATE TABLE IF NOT EXISTS users (55id INTEGER PRIMARY KEY AUTOINCREMENT,56email TEXT UNIQUE NOT NULL,57name TEXT NOT NULL,58created_at TEXT DEFAULT CURRENT_TIMESTAMP,59updated_at TEXT DEFAULT CURRENT_TIMESTAMP60);6162CREATE INDEX idx_users_email ON users(email);6364CREATE TABLE IF NOT EXISTS posts (65id INTEGER PRIMARY KEY AUTOINCREMENT,66user_id INTEGER NOT NULL,67title TEXT NOT NULL,68content TEXT,69published BOOLEAN DEFAULT 0,70created_at TEXT DEFAULT CURRENT_TIMESTAMP,71FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE72);7374CREATE INDEX idx_posts_user_id ON posts(user_id);75CREATE INDEX idx_posts_published ON posts(published);76```7778### Running Migrations7980```bash81# Create new migration file82wrangler d1 migrations create <db-name> add_users_table83# Creates: migrations/0001_add_users_table.sql8485# Apply migrations86wrangler d1 migrations apply <db-name> --local # Apply to local DB87wrangler d1 migrations apply <db-name> --remote # Apply to production DB8889# List applied migrations90wrangler d1 migrations list <db-name> --remote9192# Direct SQL execution (bypasses migration tracking)93wrangler d1 execute <db-name> --remote --command="SELECT * FROM users"94wrangler d1 execute <db-name> --local --file=./schema.sql95```9697**Migration tracking**: Wrangler creates `d1_migrations` table automatically to track applied migrations9899## Indexing Strategy100101```sql102-- Index frequently queried columns103CREATE INDEX idx_users_email ON users(email);104105-- Composite indexes for multi-column queries106CREATE INDEX idx_posts_user_published ON posts(user_id, published);107108-- Covering indexes (include queried columns)109CREATE INDEX idx_users_email_name ON users(email, name);110111-- Partial indexes for filtered queries112CREATE INDEX idx_active_users ON users(email) WHERE active = 1;113114-- Check if query uses index115EXPLAIN QUERY PLAN SELECT * FROM users WHERE email = ?;116```117118## Drizzle ORM119120```typescript121// drizzle.config.ts122export default {123schema: './src/schema.ts', out: './migrations', dialect: 'sqlite', driver: 'd1-http',124dbCredentials: { accountId: process.env.CLOUDFLARE_ACCOUNT_ID!, databaseId: process.env.D1_DATABASE_ID!, token: process.env.CLOUDFLARE_API_TOKEN! }125} satisfies Config;126127// schema.ts128import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';129export const users = sqliteTable('users', {130id: integer('id').primaryKey({ autoIncrement: true }),131email: text('email').notNull().unique(),132name: text('name').notNull()133});134135// worker.ts136import { drizzle } from 'drizzle-orm/d1';137import { users } from './schema';138export default {139async fetch(request: Request, env: Env) {140const db = drizzle(env.DB);141return Response.json(await db.select().from(users));142}143}144```145146## Import & Export147148```bash149# Export full database (schema + data)150wrangler d1 export <db-name> --remote --output=./backup.sql151152# Export data only (no schema)153wrangler d1 export <db-name> --remote --no-schema --output=./data-only.sql154155# Export with foreign key constraints preserved156# (Default: foreign keys are disabled during export for import compatibility)157158# Import SQL file159wrangler d1 execute <db-name> --remote --file=./backup.sql160161# Limitations162# - BLOB data may not export correctly (use R2 for binary files)163# - Very large exports (>1GB) may timeout (split into chunks)164# - Import is NOT atomic (use batch() for transactional imports in Workers)165```166167## Plan Tiers168169| Feature | Free (Workers Free) | Paid (Workers Paid) |170|---------|---------------------|---------------------|171| Rows read | 5 million / day | First 25 billion / month included |172| Rows written | 100,000 / day | First 50 million / month included |173| Storage | 5 GB (total) | First 5 GB included |174| Database size | 500 MB | 10 GB |175| Batch size | 1,000 statements | 10,000 statements |176| Time Travel | 7 days | 30 days |177| Read replicas | ❌ | ✅ |178| Sessions API | ❌ | ✅ (up to 15 min) |179| Pricing | Free | $5/mo + usage |180181**Usage pricing** (paid plans, beyond included allowances): $0.001 per million rows read + $1.00 per million rows written + $0.75/GB-mo storage182183## Local Development184185```bash186wrangler dev --persist-to=./.wrangler/state # Persist across restarts187# Local DB: .wrangler/state/v3/d1/<database-id>.sqlite188sqlite3 .wrangler/state/v3/d1/<database-id>.sqlite # Inspect189190# Local dev uses free tier limits by default191```192