with one click
preferences-cloudflare-wrangler-reference
// Cloudflare wrangler comprehensive reference for Workers, D1, R2, and KV configuration. Load when working with Cloudflare deployment or wrangler.toml.
// Cloudflare wrangler comprehensive reference for Workers, D1, R2, and KV configuration. Load when working with Cloudflare deployment or wrangler.toml.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | preferences-cloudflare-wrangler-reference |
| description | Cloudflare wrangler comprehensive reference for Workers, D1, R2, and KV configuration. Load when working with Cloudflare deployment or wrangler.toml. |
Comprehensive configuration reference for Cloudflare Wrangler synthesized from production patterns.
See @~/.claude/skills/preferences-web-application-deployment/SKILL.md for deployment workflows and practical patterns.
{
// JSON schema for IDE autocomplete and validation
"$schema": "node_modules/wrangler/config-schema.json"
}
Enable autocomplete and validation in your IDE by including the schema reference at the top of wrangler.jsonc.
{
// Worker name - used as deployment identifier
"name": "my-cloudflare-worker",
// Entry point for the worker
// Can be .ts, .js, or .mjs - build tools handle transpilation
"main": "src/index.ts"
}
{
// Compatibility date - locks API behavior to specific date
// Use recent date to get latest features
"compatibility_date": "2025-04-10",
// Compatibility flags - enable specific runtime features
"compatibility_flags": [
"nodejs_compat" // Enable Node.js compatibility layer
]
}
Important: Update compatibility_date regularly to access new platform features.
{
// Enable workers.dev subdomain for testing
// Set to false in production to avoid accidental exposure
"workers_dev": true
}
Serve static assets alongside worker logic (SPAs, SSR apps).
{
"assets": {
// Directory containing static assets to serve
"directory": ".output/public",
// Binding name to access assets in worker code
"binding": "ASSETS",
// Handle 404s as SPA - serve index.html for missing routes
"not_found_handling": "single-page-application",
// Patterns where worker runs before checking for static assets
// Useful for API routes, auth endpoints, or dynamic paths
"run_worker_first": ["/api/*", "/trpc/*", "/auth/*"]
}
}
Pattern: TanStack Start or similar SSR frameworks serve frontend assets while worker handles API routes.
{
"build": {
// Command to run before deployment
"command": "bun run build",
// Working directory for build command
"cwd": ".",
// Directories to watch during `wrangler dev`
"watch_dir": "src"
}
}
Alternative: Use framework-specific build tools (Vite, etc.) and skip wrangler build command.
{
"routes": [
{
// Custom domain routing (requires DNS setup in Cloudflare)
"pattern": "example.com",
"custom_domain": true
},
{
// Zone-based routing with wildcard pattern
"zone_name": "example.com",
"pattern": "api.example.com/*"
}
]
}
Setup:
{
"observability": {
// Enable metrics, logs, and traces in Cloudflare dashboard
"enabled": true
}
}
Access observability data: Cloudflare Dashboard > Workers & Pages > [Your Worker] > Metrics
Automatically places worker near users for optimal latency.
{
"placement": {
"mode": "smart"
}
}
When to use: Geographic user distribution with latency-sensitive workloads.
See: https://developers.cloudflare.com/workers/configuration/smart-placement/
{
"vars": {
"API_URL": "https://api.example.com",
"FEATURE_FLAG_NEW_UI": "true",
"LOG_LEVEL": "info"
}
}
Access in worker:
import { env } from "cloudflare:workers";
const apiUrl = env.API_URL;
const featureEnabled = env.FEATURE_FLAG_NEW_UI === "true";
Secrets not stored in wrangler.jsonc - managed via CLI:
# Set secret
wrangler secret put DATABASE_PASSWORD
# List secrets
wrangler secret list
# Delete secret
wrangler secret delete OLD_SECRET
# Set secret for specific environment
wrangler secret put API_KEY --env production
Access in worker (same as vars):
import { env } from "cloudflare:workers";
const dbPassword = env.DATABASE_PASSWORD;
Connect to Cloudflare platform resources.
See: https://developers.cloudflare.com/workers/runtime-apis/bindings/
{
"d1_databases": [
{
"binding": "DB", // Access via env.DB in worker code
"database_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"database_name": "my-app-db",
"experimental_remote": true // Allow remote access during local dev
}
]
}
Usage:
import { drizzle } from "drizzle-orm/d1";
const db = drizzle(env.DB);
const users = await db.select().from(usersTable);
Create database:
wrangler d1 create my-app-db
{
"kv_namespaces": [
{
"binding": "CACHE",
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"experimental_remote": true
}
]
}
Usage:
// Write
await env.CACHE.put("key", "value", {
expirationTtl: 3600 // 1 hour
});
// Read
const value = await env.CACHE.get("key");
// Read as JSON
const data = await env.CACHE.get("key", "json");
// Delete
await env.CACHE.delete("key");
// List keys
const list = await env.CACHE.list();
Create namespace:
wrangler kv namespace create CACHE
{
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "my-storage-bucket"
}
]
}
Usage (S3-compatible API):
// Upload object
await env.BUCKET.put("uploads/file.pdf", fileData, {
httpMetadata: {
contentType: "application/pdf"
}
});
// Download object
const file = await env.BUCKET.get("uploads/file.pdf");
const blob = await file.blob();
// Delete object
await env.BUCKET.delete("uploads/file.pdf");
// List objects
const list = await env.BUCKET.list({ prefix: "uploads/" });
Create bucket:
wrangler r2 bucket create my-storage-bucket
{
"services": [
{
"binding": "BACKEND_SERVICE",
"service": "data-service-production",
"experimental_remote": true // Enable service-to-service calls in dev
}
]
}
Usage:
// Call another worker service
const response = await env.BACKEND_SERVICE.fetch(
new Request("https://internal/api/data", {
method: "POST",
body: JSON.stringify({ query: "..." })
})
);
const data = await response.json();
Pattern: Microservices architecture with multiple workers.
apps/
user-application/ # Frontend worker
data-service/ # Backend API worker
auth-service/ # Authentication worker
{
"browser": {
"binding": "VIRTUAL_BROWSER"
}
}
Usage:
const browser = await env.VIRTUAL_BROWSER.launch();
const page = await browser.newPage();
await page.goto("https://example.com");
// Take screenshot
const screenshot = await page.screenshot();
// Get page content
const html = await page.content();
await browser.close();
Use cases: Web scraping, PDF generation, automated testing, SEO previews.
{
"ai": {
"binding": "AI"
}
}
Usage:
// Text generation
const response = await env.AI.run("@cf/meta/llama-2-7b-chat-int8", {
prompt: "What is the capital of France?"
});
// Image classification
const result = await env.AI.run("@cf/microsoft/resnet-50", {
image: imageData
});
// Text embeddings
const embeddings = await env.AI.run("@cf/baai/bge-base-en-v1.5", {
text: "Hello world"
});
See: https://developers.cloudflare.com/workers-ai/
{
"queues": {
"consumers": [
{
"queue": "data-processing-queue",
"dead_letter_queue": "data-processing-dlq" // Failed messages route here
},
{
"queue": "data-processing-dlq",
"retry_delay": 0 // Manual retry for DLQ messages
}
],
"producers": [
{
"binding": "QUEUE",
"queue": "data-processing-queue"
}
]
}
}
Producer usage:
// Send single message
await env.QUEUE.send({
userId: "123",
action: "process_upload"
});
// Batch send
await env.QUEUE.sendBatch([
{ body: { userId: "123" } },
{ body: { userId: "456" } }
]);
Consumer handler:
export default {
async queue(batch: MessageBatch, env: Env): Promise<void> {
for (const message of batch.messages) {
try {
await processMessage(message.body);
message.ack();
} catch (error) {
message.retry(); // Retry or send to DLQ
}
}
}
}
Create queue:
wrangler queues create data-processing-queue
wrangler queues create data-processing-dlq
Long-running, durable processes that survive worker restarts.
{
"workflows": [
{
"binding": "MY_WORKFLOW",
"name": "my-workflow-production",
"class_name": "MyWorkflow" // Must match exported class in code
}
]
}
Workflow definition:
import { WorkflowEntrypoint, WorkflowStep } from "cloudflare:workers";
export class MyWorkflow extends WorkflowEntrypoint {
async run(event: any, step: WorkflowStep) {
// Steps are checkpointed - execution resumes on failure
const result1 = await step.do("fetch-data", async () => {
return await fetch("https://api.example.com/data");
});
// Sleep preserves state
await step.sleep("wait-for-processing", "1 hour");
const result2 = await step.do("process-data", async () => {
return processData(result1);
});
return result2;
}
}
Trigger workflow:
const instance = await env.MY_WORKFLOW.create({
params: { userId: "123" }
});
// Check status
const status = await instance.status();
Strongly consistent, stateful workers with persistent storage.
{
"durable_objects": {
"bindings": [
{
"name": "TRACKER_OBJECT",
"class_name": "EventTracker"
},
{
"name": "SCHEDULER_OBJECT",
"class_name": "TaskScheduler"
}
]
}
}
Durable Object migrations:
Required when adding or modifying Durable Objects.
{
"migrations": [
{
"tag": "v1",
"new_classes": ["TaskScheduler"] // Standard Durable Object
},
{
"tag": "v2",
"new_sqlite_classes": ["EventTracker"] // DO with SQLite storage
}
]
}
Durable Object definition:
import { DurableObject } from "cloudflare:workers";
export class EventTracker extends DurableObject {
async fetch(request: Request) {
// Strongly consistent storage
let count = (await this.ctx.storage.get<number>("count")) || 0;
count++;
await this.ctx.storage.put("count", count);
return new Response(count.toString());
}
// WebSocket connections
async webSocketMessage(ws: WebSocket, message: string) {
// Handle WebSocket messages
}
}
Access from worker:
// Create unique Durable Object instance
const id = env.TRACKER_OBJECT.idFromName("global-tracker");
const stub = env.TRACKER_OBJECT.get(id);
// Call Durable Object
const response = await stub.fetch(request);
Use cases: Chat rooms, collaborative editing, counters, rate limiting, session management.
Override any top-level setting per environment.
{
"name": "my-app",
// Default configuration (used for wrangler dev)
"vars": {
"API_URL": "https://api-dev.example.com",
"STRIPE_PRODUCT_ID": "price_dev_xxxxx"
},
"d1_databases": [
{
"binding": "DB",
"database_id": "dev-database-id",
"experimental_remote": true
}
],
// Environment-specific overrides
"env": {
"stage": {
"vars": {
"API_URL": "https://api-stage.example.com",
"STRIPE_PRODUCT_ID": "price_staging_xxxxx"
},
"routes": [
{
"custom_domain": true,
"pattern": "stage.example.com"
}
],
"d1_databases": [
{
"binding": "DB",
"database_id": "stage-database-id",
"experimental_remote": true
}
],
"kv_namespaces": [
{
"binding": "CACHE",
"id": "stage-kv-namespace-id"
}
],
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "my-storage-stage"
}
],
"services": [
{
"binding": "BACKEND_SERVICE",
"service": "data-service-stage",
"experimental_remote": true
}
],
"queues": {
"consumers": [
{
"queue": "data-queue-stage",
"dead_letter_queue": "data-dlq-stage"
}
],
"producers": [
{
"binding": "QUEUE",
"queue": "data-queue-stage"
}
]
}
},
"production": {
"vars": {
"API_URL": "https://api.example.com",
"STRIPE_PRODUCT_ID": "price_production_xxxxx"
},
"routes": [
{
"custom_domain": true,
"pattern": "example.com"
}
],
"d1_databases": [
{
"binding": "DB",
"database_id": "production-database-id"
}
],
"kv_namespaces": [
{
"binding": "CACHE",
"id": "production-kv-namespace-id"
}
],
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "my-storage-production"
}
],
"services": [
{
"binding": "BACKEND_SERVICE",
"service": "data-service-production"
}
],
"queues": {
"consumers": [
{
"queue": "data-queue-production",
"dead_letter_queue": "data-dlq-production"
}
],
"producers": [
{
"binding": "QUEUE",
"queue": "data-queue-production"
}
]
}
}
}
}
Deploy to environment:
# Deploy to staging
wrangler deploy --env stage
# Deploy to production
wrangler deploy --env production
# Local development (uses default config)
wrangler dev
Environment-specific secrets:
wrangler secret put DATABASE_PASSWORD --env stage
wrangler secret put DATABASE_PASSWORD --env production
Custom analytics with high-cardinality data.
{
"analytics_engine_datasets": [
{
"binding": "ANALYTICS"
}
]
}
Usage:
env.ANALYTICS.writeDataPoint({
// String dimensions
blobs: ["user_signup", "web"],
// Numeric values
doubles: [1, userId],
// Indexed fields for querying
indexes: [userId],
});
Query in dashboard: GraphQL API or SQL API for analytics queries.
{
"version_metadata": {
"binding": "CF_VERSION_METADATA"
}
}
Usage:
const metadata = env.CF_VERSION_METADATA;
console.log(`Version ID: ${metadata.id}`);
console.log(`Deployed at: ${metadata.timestamp}`);
Process logs from other workers in real-time.
{
"tail_consumers": [
{
"service": "log-aggregator"
}
]
}
Log consumer worker:
export default {
async tail(events: TraceItem[], env: Env) {
for (const event of events) {
// Process logs, errors, traces
await env.DB.prepare(
"INSERT INTO logs (message, timestamp) VALUES (?, ?)"
).bind(event.logs[0].message, event.eventTimestamp).run();
}
}
}
Deploy user-provided workers dynamically.
{
"dispatch_namespaces": [
{
"binding": "DISPATCHER",
"namespace": "user-workers"
}
]
}
Usage:
// Deploy user worker
await env.DISPATCHER.put("user-123-worker", workerScript);
// Execute user worker
const worker = env.DISPATCHER.get("user-123-worker");
const response = await worker.fetch(request);
Use case: SaaS platforms allowing customers to deploy custom workers.
Mutual TLS for secure service-to-service communication.
{
"mtls_certificates": [
{
"binding": "MTLS_CERT",
"certificate_id": "cert-id"
}
]
}
Usage:
const response = await fetch("https://api.example.com", {
mtls: {
certificate_id: env.MTLS_CERT
}
});
Stream logs to external destinations (S3, R2, HTTP).
{
"logpush": true
}
Configure logpush destinations in Cloudflare dashboard.
{
"limits": {
"cpu_ms": 50
}
}
Set CPU time limits per request (default 10ms on free tier, 50ms on paid).
{
"triggers": {
"crons": [
"0 0 * * *" // Daily at midnight UTC
]
}
}
Handler:
export default {
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext) {
// Run scheduled task
await cleanupExpiredData(env.DB);
}
}