Cloudflare Workers Cheat Sheet
Build and deploy serverless functions at the edge with Cloudflare Workers, Wrangler CLI, KV storage, and Durable Objects basics.
Wrangler CLI Basics
Scaffold, develop, and deploy Workers with Wrangler.
npm create cloudflare@latest my-worker # Scaffold a new Workercd my-workernpx wrangler login # Authenticate with Cloudflarenpx wrangler dev # Run locally with hot reloadnpx wrangler deploy # Deploy to productionnpx wrangler tail # Stream live logs from a deployed Workernpx wrangler kv:namespace create MY_KV # Create a KV namespacenpx wrangler secret put API_KEY # Store an encrypted secret
Worker Fetch Handler
Basic module-syntax Worker responding to HTTP requests.
export default { async fetch(request, env, ctx) { const url = new URL(request.url); if (url.pathname === '/api/time') { return new Response(JSON.stringify({ now: Date.now() }), { headers: { 'content-type': 'application/json' }, }); } return new Response('Not found', { status: 404 }); },};
wrangler.toml Config
Declare bindings, routes, and compatibility settings.
name = "my-worker"main = "src/index.js"compatibility_date = "2024-01-01"[[kv_namespaces]]binding = "MY_KV"id = "abcd1234"[vars]ENVIRONMENT = "production"[[routes]]pattern = "example.com/api/*"zone_name = "example.com"
Core Concepts
Key primitives available in the Workers runtime.
- env bindings- KV, R2, D1, and secrets are injected into the handler via the `env` parameter, not global variables
- KV (Workers KV)- eventually-consistent key-value store, accessed via `env.MY_KV.get()` / `.put()`
- R2- S3-compatible object storage with zero egress fees
- D1- serverless SQLite database that runs at the edge
- Durable Objects- stateful, single-instance objects for coordination (e.g. chat rooms, counters)
- ctx.waitUntil()- extends the Worker's lifetime to finish async work after the response is sent
- Cron Triggers- scheduled Workers configured via `[triggers] crons = [...]` in wrangler.toml
Durable Object: Coordinated Counter
Define a Durable Object class for strongly-consistent, single-instance state across requests.
export class Counter { constructor(state, env) { this.state = state; } async fetch(request) { let value = (await this.state.storage.get('value')) || 0; if (request.method === 'POST') { value += 1; await this.state.storage.put('value', value); } return new Response(String(value)); }}// index.jsexport default { async fetch(request, env) { const id = env.COUNTER.idFromName('global'); const stub = env.COUNTER.get(id); return stub.fetch(request); },};
D1 Database Query
Run parameterized SQL against a D1 database bound to the Worker.
export default { async fetch(request, env) { const { pathname } = new URL(request.url); if (pathname === '/users') { const { results } = await env.DB.prepare( 'SELECT id, email FROM users WHERE active = ?' ).bind(1).all(); return Response.json(results); } // batch write in a single round trip await env.DB.batch([ env.DB.prepare('INSERT INTO logs (msg) VALUES (?)').bind('hit'), ]); return new Response('ok'); },};
HTMLRewriter Streaming Transform
Rewrite HTML on the fly while streaming an origin response, without buffering the whole body.
class LinkRewriter { element(el) { const href = el.getAttribute('href'); if (href && href.startsWith('http://')) { el.setAttribute('href', href.replace('http://', 'https://')); } }}export default { async fetch(request) { const res = await fetch('https://origin.example.com'); return new HTMLRewriter() .on('a[href]', new LinkRewriter()) .transform(res); },};
Service Bindings (Worker-to-Worker RPC)
Call another Worker directly over a zero-latency binding instead of an HTTP fetch.
// wrangler.toml (caller)// [[services]]// binding = "AUTH"// service = "auth-worker"export default { async fetch(request, env) { // env.AUTH is bound directly to the other Worker's fetch handler const authRes = await env.AUTH.fetch('https://internal/verify', { headers: { authorization: request.headers.get('authorization') }, }); if (!authRes.ok) return new Response('Unauthorized', { status: 401 }); return new Response('Welcome'); },};
Advanced Platform Features
Beyond KV/R2/D1 basics: primitives for scale, resilience, and observability.
- Queues- durable message queue producer/consumer bindings for decoupling async work between Workers
- Smart Placement- Cloudflare automatically runs a Worker closer to its backend origin/DB instead of the request's edge PoP when that's faster
- Cache API- `caches.default.match()/put()` gives explicit programmatic control over the edge cache beyond `Cache-Control` headers
- Hyperdrive- connection-pooling proxy that makes regional Postgres/MySQL fast to query from Workers globally
- mTLS bindings- attach a client certificate to a binding so a Worker can call origins requiring mutual TLS
- Workers Analytics Engine- write arbitrary time-series data points from a Worker for custom metrics without an external APM
- Static Assets binding- serve a built SPA/static site directly from a Worker via `env.ASSETS.fetch()`, unifying static + API in one deploy
Workers have strict CPU-time limits (not wall-clock time), so `ctx.waitUntil()` is the right tool for logging or cache-writes after responding — but any CPU-bound work still counts against your execution limit even inside it.