Workers Fundamentals
Cloudflare Workers runtime fundamentals including V8 isolates, wrangler CLI, project setup, local development, deployment, environment variables, secrets, and compatibility dates.
You are an expert in Cloudflare Workers, the serverless edge compute platform that runs JavaScript, TypeScript, and WebAssembly on Cloudflare's global network using V8 isolates. ## Key Points - **CPU time limits**: Free plan gets 10 ms CPU time per invocation; paid plan gets 30 seconds. - **Memory**: 128 MB per isolate. - **No Node.js built-ins by default**: Workers use Web Standard APIs (fetch, crypto, streams, etc.). Node.js compat is opt-in via `nodejs_compat` flag. - **No file system**: There is no `fs` module. Use KV, R2, or D1 for persistence. - **Request-scoped execution**: Workers run in response to events (HTTP requests, cron triggers, queue messages). - `ctx.waitUntil(promise)` — Keeps the Worker alive after returning a response. Use for background tasks like logging, analytics, or cache writes. - `ctx.passThroughOnException()` — Falls through to origin server if the Worker throws. - **"exceeded CPU time limit"** — Optimize hot paths, avoid synchronous heavy computation, consider breaking work across multiple requests or using Durable Objects. - **"exceeded subrequest limit"** — Free plan allows 50 subrequests; paid allows 1000. Batch operations where possible. - **"compatibility flag required"** — Add the required flag to `compatibility_flags` in `wrangler.toml`. - **Debugging** — Use `wrangler tail` for live logs, `console.log()` for local dev, and the Cloudflare dashboard for error analytics. ## Quick Example ```bash npm install -g wrangler # Or use npx npx wrangler init my-worker ``` ```bash npx wrangler init my-worker cd my-worker ```
skilldb get cloudflare-workers-skills/Workers FundamentalsFull skill: 354 linesWorkers Fundamentals — Cloudflare Workers
You are an expert in Cloudflare Workers, the serverless edge compute platform that runs JavaScript, TypeScript, and WebAssembly on Cloudflare's global network using V8 isolates.
Core Philosophy
Overview
Cloudflare Workers run on V8 isolates—not containers or VMs. Each Worker executes in a lightweight V8 isolate that starts in under 5 milliseconds, uses minimal memory, and runs in 300+ data centers worldwide. This architecture gives sub-millisecond cold starts and automatic global distribution without any infrastructure management.
Key constraints
- CPU time limits: Free plan gets 10 ms CPU time per invocation; paid plan gets 30 seconds.
- Memory: 128 MB per isolate.
- No Node.js built-ins by default: Workers use Web Standard APIs (fetch, crypto, streams, etc.). Node.js compat is opt-in via
nodejs_compatflag. - No file system: There is no
fsmodule. Use KV, R2, or D1 for persistence. - Request-scoped execution: Workers run in response to events (HTTP requests, cron triggers, queue messages).
Project Setup
Install wrangler
npm install -g wrangler
# Or use npx
npx wrangler init my-worker
Create a new project
npx wrangler init my-worker
cd my-worker
This generates a wrangler.toml configuration file and a src/index.ts entry point.
wrangler.toml — the configuration file
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-09-23"
compatibility_flags = ["nodejs_compat"]
# Account-level settings
account_id = "your-account-id"
# Environment variables (non-secret)
[vars]
ENVIRONMENT = "production"
API_BASE_URL = "https://api.example.com"
# KV namespace binding
[[kv_namespaces]]
binding = "MY_KV"
id = "abc123"
preview_id = "def456"
# D1 database binding
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxxx-yyyy-zzzz"
# R2 bucket binding
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"
Compatibility dates
The compatibility_date field pins your Worker to a specific set of runtime behaviors. Cloudflare may change default behaviors over time; the compatibility date ensures your Worker is unaffected. Always set this to a recent date when starting a new project and update it periodically.
compatibility_date = "2024-09-23"
compatibility_flags = ["nodejs_compat"]
The Worker Entry Point
ES modules syntax (recommended)
export interface Env {
MY_KV: KVNamespace;
DB: D1Database;
BUCKET: R2Bucket;
API_KEY: string;
ENVIRONMENT: string;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === "/health") {
return new Response("OK", { status: 200 });
}
return new Response("Hello from Cloudflare Workers!", {
headers: { "content-type": "text/plain" },
});
},
};
ExecutionContext
The ctx parameter provides:
ctx.waitUntil(promise)— Keeps the Worker alive after returning a response. Use for background tasks like logging, analytics, or cache writes.ctx.passThroughOnException()— Falls through to origin server if the Worker throws.
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
// Return response immediately
const response = new Response("Accepted", { status: 202 });
// Log analytics in the background without blocking the response
ctx.waitUntil(
fetch("https://analytics.example.com/log", {
method: "POST",
body: JSON.stringify({ path: new URL(request.url).pathname }),
})
);
return response;
},
};
Environment Variables and Secrets
Plain variables in wrangler.toml
[vars]
ENVIRONMENT = "staging"
LOG_LEVEL = "debug"
Secrets (sensitive values)
Never put secrets in wrangler.toml. Use the CLI:
# Set a secret
npx wrangler secret put API_KEY
# Prompts for the value interactively
# List secrets
npx wrangler secret list
# Delete a secret
npx wrangler secret delete API_KEY
Secrets are accessed the same way as variables — through the env parameter:
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const apiKey = env.API_KEY; // secret
const environment = env.ENVIRONMENT; // plain var
// ...
},
};
Per-environment configuration
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-09-23"
[vars]
ENVIRONMENT = "production"
[env.staging]
vars = { ENVIRONMENT = "staging" }
[env.staging.routes]
pattern = "staging.example.com/*"
Deploy to a specific environment:
npx wrangler deploy --env staging
Local Development
wrangler dev
# Start local dev server
npx wrangler dev
# With local persistence for KV, D1, R2
npx wrangler dev --persist-to=.wrangler/state
# Bind to a specific port
npx wrangler dev --port 8787
# Use remote resources instead of local emulation
npx wrangler dev --remote
wrangler dev uses Miniflare under the hood, which faithfully emulates the Workers runtime locally. Local KV, D1, and R2 data persists across restarts when using --persist-to.
Testing with Vitest
// vitest.config.ts
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
wrangler: { configPath: "./wrangler.toml" },
},
},
},
});
// src/index.test.ts
import { describe, it, expect } from "vitest";
import { SELF } from "cloudflare:test";
describe("Worker", () => {
it("responds with hello", async () => {
const response = await SELF.fetch("https://example.com/");
expect(response.status).toBe(200);
expect(await response.text()).toBe("Hello from Cloudflare Workers!");
});
});
Deployment
Deploy to production
# Deploy
npx wrangler deploy
# Deploy with a specific name
npx wrangler deploy --name my-worker-v2
# Tail logs in real time
npx wrangler tail
# View deployment history
npx wrangler deployments list
# Rollback to a previous deployment
npx wrangler rollback
Custom domains and routes
# Route patterns
routes = [
{ pattern = "api.example.com/*", zone_name = "example.com" }
]
# Or use custom domains (simpler, auto-creates DNS records)
[custom_domain]
hostname = "api.example.com"
Common Patterns
JSON API response helper
function json(data: unknown, status = 200): Response {
return new Response(JSON.stringify(data), {
status,
headers: { "content-type": "application/json" },
});
}
function error(message: string, status = 500): Response {
return json({ error: message }, status);
}
Reading request body
async function handlePost(request: Request): Promise<Response> {
const contentType = request.headers.get("content-type") || "";
if (contentType.includes("application/json")) {
const body = await request.json();
return json({ received: body });
}
if (contentType.includes("form")) {
const formData = await request.formData();
const name = formData.get("name");
return json({ name });
}
const text = await request.text();
return json({ raw: text });
}
Subrequest fan-out
Workers can make up to 1000 subrequests per invocation (paid plan):
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const urls = [
"https://api.example.com/users",
"https://api.example.com/posts",
"https://api.example.com/comments",
];
const results = await Promise.all(
urls.map((url) => fetch(url).then((r) => r.json()))
);
return json({ users: results[0], posts: results[1], comments: results[2] });
},
};
Troubleshooting
- "exceeded CPU time limit" — Optimize hot paths, avoid synchronous heavy computation, consider breaking work across multiple requests or using Durable Objects.
- "exceeded subrequest limit" — Free plan allows 50 subrequests; paid allows 1000. Batch operations where possible.
- "compatibility flag required" — Add the required flag to
compatibility_flagsinwrangler.toml. - Debugging — Use
wrangler tailfor live logs,console.log()for local dev, and the Cloudflare dashboard for error analytics.
Install this skill directly: skilldb add cloudflare-workers-skills
Related Skills
Durable Objects
Cloudflare Durable Objects for stateful edge computing, covering constructor patterns, storage API, WebSocket support, alarm handlers, consistency guarantees, and use cases like rate limiting, collaboration, and game state.
Workers AI
Cloudflare Workers AI for running inference at the edge, covering supported models, text generation, embeddings, image generation, speech-to-text, AI bindings, and streaming responses.
Workers D1
Cloudflare D1 serverless SQLite database for Workers, covering schema management, migrations, queries, prepared statements, batch operations, local development, replication, backups, and performance optimization.
Workers KV
Cloudflare Workers KV namespace for globally distributed key-value storage, including read/write patterns, caching strategies, TTL, list operations, metadata, bulk operations, and the eventual consistency model.
Workers Patterns
Production patterns for Cloudflare Workers including queue consumers, cron triggers, email workers, browser rendering, Hyperdrive database connection pooling, Vectorize vector search, and the analytics engine.
Workers R2
Cloudflare R2 object storage with S3-compatible API, covering bucket operations, multipart uploads, presigned URLs, public buckets, lifecycle rules, event notifications, and cost optimization compared to S3.