cloudflare-workers
π―Skillfrom akornmeier/claude-config
Enables building and deploying serverless edge functions across Cloudflare's global network using JavaScript, TypeScript, Python, and Rust.
Part of
akornmeier/claude-config(24 items)
Installation
npm install -g wranglerSkill Details
Comprehensive guide for building serverless applications with Cloudflare Workers. Use when developing Workers, configuring bindings, implementing runtime APIs, testing Workers, using Wrangler CLI, deploying to production, or building edge functions with JavaScript/TypeScript/Python/Rust.
Overview
# Cloudflare Workers Skill
Cloudflare Workers is a serverless execution environment that runs JavaScript, TypeScript, Python, and Rust code on Cloudflare's global edge network across 300+ cities worldwide.
Reference
- Main Documentation: https://developers.cloudflare.com/workers/
- Runtime APIs: https://developers.cloudflare.com/workers/runtime-apis/
- Examples: https://developers.cloudflare.com/workers/examples/
- Wrangler CLI: https://developers.cloudflare.com/workers/wrangler/
When to Use This Skill
Use this skill when:
- Creating new Cloudflare Workers applications
- Configuring Worker bindings (D1, KV, R2, Durable Objects, etc.)
- Implementing Worker runtime APIs (fetch, cache, HTMLRewriter, WebSockets)
- Writing and testing Workers locally with Wrangler
- Deploying Workers to production
- Implementing cron triggers and scheduled jobs
- Building API endpoints and middleware
- Working with Workers static assets
- Setting up CI/CD for Workers
- Migrating from service workers to ES modules
- Debugging and monitoring Workers
- Optimizing Worker performance
Core Concepts
Execution Model
V8 Isolates: Workers run in lightweight V8 isolates (not containers):
- Millisecond cold starts (faster than containers)
- Zero infrastructure management
- Automatic global scaling
- Pay-per-request pricing
Request Lifecycle:
- Request arrives at nearest Cloudflare data center
- Worker executes in V8 isolate
- Response returned to client
- Isolate may be reused for subsequent requests
Key Characteristics:
- Maximum CPU time: 50ms (Free), 30 seconds (Paid)
- Maximum memory: 128MB
- Executes at the edge (closest to user)
- No state between requests (use Durable Objects for state)
Worker Formats
ES Modules (Recommended):
```typescript
// Modern syntax with export default
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise
return new Response('Hello World!');
},
};
```
Service Worker (Legacy):
```javascript
// Legacy format
addEventListener('fetch', (event) => {
event.respondWith(new Response('Hello World!'));
});
```
Handler Types
Workers support multiple event types:
Fetch Handler (HTTP requests):
```typescript
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise
return new Response('Hello');
},
};
```
Scheduled Handler (Cron jobs):
```typescript
export default {
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise
// Runs on schedule
await fetch('https://api.example.com/cleanup');
},
};
```
Queue Handler (Message processing):
```typescript
export default {
async queue(batch: MessageBatch, env: Env, ctx: ExecutionContext): Promise
for (const message of batch.messages) {
await processMessage(message.body);
}
},
};
```
Email Handler (Email routing):
```typescript
export default {
async email(message: ForwardableEmailMessage, env: Env, ctx: ExecutionContext): Promise
await message.forward('destination@example.com');
},
};
```
Tail Handler (Log aggregation):
```typescript
export default {
async tail(events: TraceItem[], env: Env, ctx: ExecutionContext): Promise
// Process logs from other Workers
},
};
```
Wrangler CLI
Installation & Setup
```bash
# Install globally
npm install -g wrangler
# Or use npx
npx wrangler
# Login to Cloudflare
wrangler login
# Check version
wrangler --version
```
Project Management
```bash
# Create new Worker
wrangler init my-worker
# Options: TypeScript, Git, deploy
# Create with template
wrangler init my-worker --template
# Development server
wrangler dev # Local mode
wrangler dev --remote # Remote mode (actual edge)
wrangler dev --port 8080 # Custom port
# Deploy
wrangler deploy # Production
wrangler deploy --dry-run # Preview changes
wrangler deploy --env staging # Specific environment
# Logs
wrangler tail # Real-time logs
wrangler tail --format pretty # Formatted output
wrangler tail --status error # Filter by status
# Versions & Rollback
wrangler deployments list
wrangler rollback [version-id]
wrangler versions list
```
Configuration (wrangler.toml)
```toml
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"
compatibility_flags = ["nodejs_compat"]
# Routes
routes = [
{ pattern = "example.com/*", zone_name = "example.com" }
]
# Or use custom domains
# [[routes]]
# pattern = "api.example.com/*"
# custom_domain = true
# Environment variables
[vars]
ENVIRONMENT = "production"
API_VERSION = "v1"
# Cron triggers
[triggers]
crons = ["0 0 *"] # Daily at midnight
# Build configuration
[build]
command = "npm run build"
watch_dirs = ["src"]
# Environments
[env.staging]
name = "my-worker-staging"
routes = [
{ pattern = "staging.example.com/*", zone_name = "example.com" }
]
[env.staging.vars]
ENVIRONMENT = "staging"
```
Secrets Management
```bash
# Add secret
wrangler secret put API_KEY
# Enter value when prompted
# List secrets
wrangler secret list
# Delete secret
wrangler secret delete API_KEY
# Bulk upload
echo "VALUE" | wrangler secret put API_KEY
```
Runtime APIs
Fetch API
```typescript
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise
// Parse URL
const url = new URL(request.url);
// Request properties
const method = request.method;
const headers = request.headers;
const body = await request.text();
// Subrequest
const response = await fetch('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'value' }),
});
const data = await response.json();
// Response
return new Response(JSON.stringify(data), {
status: 200,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=3600',
},
});
},
};
```
Headers API
```typescript
// Read headers
const userAgent = request.headers.get('User-Agent');
const allHeaders = Object.fromEntries(request.headers);
// Set headers
const headers = new Headers();
headers.set('Content-Type', 'application/json');
headers.append('X-Custom-Header', 'value');
// Cloudflare-specific headers
const country = request.cf?.country;
const colo = request.cf?.colo;
const clientIP = request.headers.get('CF-Connecting-IP');
// Response with headers
return new Response(body, { headers });
```
Cache API
```typescript
export default {
async fetch(request: Request): Promise
const cache = caches.default;
// Check cache
let response = await cache.match(request);
if (!response) {
// Cache miss - fetch from origin
response = await fetch(request);
// Clone and cache response
const cacheResponse = response.clone();
ctx.waitUntil(cache.put(request, cacheResponse));
}
return response;
},
};
```
Cache with custom key:
```typescript
const cacheKey = new Request(url.toString(), request);
const response = await cache.match(cacheKey);
if (!response) {
response = await fetch(request);
ctx.waitUntil(cache.put(cacheKey, response.clone()));
}
```
Cache with TTL:
```typescript
const response = await fetch('https://api.example.com/data', {
cf: {
cacheTtl: 3600,
cacheEverything: true,
cacheKey: 'custom-key',
},
});
```
HTMLRewriter
```typescript
export default {
async fetch(request: Request): Promise
const response = await fetch(request);
return new HTMLRewriter()
.on('title', {
element(element) {
element.setInnerContent('New Title');
},
})
.on('a[href]', {
element(element) {
const href = element.getAttribute('href');
element.setAttribute('href', href.replace('http://', 'https://'));
},
})
.on('script', {
element(element) {
element.remove();
},
})
.transform(response);
},
};
```
Text manipulation:
```typescript
new HTMLRewriter()
.on('p', {
text(text) {
if (text.text.includes('replace-me')) {
text.replace('new-text');
}
},
})
.transform(response);
```
WebSockets
```typescript
export default {
async fetch(request: Request): Promise
const upgradeHeader = request.headers.get('Upgrade');
if (upgradeHeader !== 'websocket') {
return new Response('Expected WebSocket', { status: 426 });
}
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
// Accept WebSocket connection
server.accept();
// Handle messages
server.addEventListener('message', (event) => {
server.send(Echo: ${event.data});
});
server.addEventListener('close', () => {
console.log('WebSocket closed');
});
return new Response(null, {
status: 101,
webSocket: client,
});
},
};
```
Streams API
```typescript
// Readable stream
const { readable, writable } = new TransformStream();
const writer = writable.getWriter();
writer.write(new TextEncoder().encode('chunk 1'));
writer.write(new TextEncoder().encode('chunk 2'));
writer.close();
return new Response(readable, {
headers: { 'Content-Type': 'text/plain' },
});
```
Stream transformation:
```typescript
const response = await fetch('https://example.com/large-file');
const { readable, writable } = new TransformStream({
transform(chunk, controller) {
// Process chunk
controller.enqueue(chunk);
},
});
response.body.pipeTo(writable);
return new Response(readable);
```
Context API
```typescript
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise
// waitUntil: Run tasks after response sent
ctx.waitUntil(
fetch('https://analytics.example.com/log', {
method: 'POST',
body: JSON.stringify({ url: request.url }),
})
);
// passThroughOnException: Continue to origin on error
ctx.passThroughOnException();
return new Response('OK');
},
};
```
Web Crypto API
```typescript
// Generate hash
const data = new TextEncoder().encode('message');
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
// HMAC signature
const key = await crypto.subtle.importKey(
'raw',
new TextEncoder().encode('secret'),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign', 'verify']
);
const signature = await crypto.subtle.sign('HMAC', key, data);
// Verify
const valid = await crypto.subtle.verify('HMAC', key, signature, data);
// Random values
const randomBytes = crypto.getRandomValues(new Uint8Array(32));
const uuid = crypto.randomUUID();
// Timing-safe comparison
const equal = crypto.timingSafeEqual(buffer1, buffer2);
```
Bindings
Environment Variables
```typescript
// wrangler.toml
[vars];
API_URL = 'https://api.example.com';
// Usage
export default {
async fetch(request: Request, env: Env): Promise
const apiUrl = env.API_URL;
return new Response(apiUrl);
},
};
```
KV Namespace
```toml
# wrangler.toml
[[kv_namespaces]]
binding = "MY_KV"
id = "your-namespace-id"
```
```typescript
export default {
async fetch(request: Request, env: Env): Promise
// Put
await env.MY_KV.put('key', 'value', {
expirationTtl: 3600,
metadata: { userId: '123' },
});
// Get
const value = await env.MY_KV.get('key');
const json = await env.MY_KV.get('key', 'json');
const buffer = await env.MY_KV.get('key', 'arrayBuffer');
const stream = await env.MY_KV.get('key', 'stream');
// Get with metadata
const { value, metadata } = await env.MY_KV.getWithMetadata('key');
// Delete
await env.MY_KV.delete('key');
// List
const list = await env.MY_KV.list({ prefix: 'user:' });
return new Response(value);
},
};
```
R2 Bucket
```toml
# wrangler.toml
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"
```
```typescript
export default {
async fetch(request: Request, env: Env): Promise
// Put object
await env.MY_BUCKET.put('file.txt', 'content', {
httpMetadata: {
contentType: 'text/plain',
contentLanguage: 'en-US',
cacheControl: 'public, max-age=3600',
},
customMetadata: {
uploadedBy: 'user123',
},
});
// Get object
const object = await env.MY_BUCKET.get('file.txt');
if (!object) {
return new Response('Not Found', { status: 404 });
}
// Return object
return new Response(object.body, {
headers: {
'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream',
ETag: object.etag,
},
});
// Delete object
await env.MY_BUCKET.delete('file.txt');
// List objects
const listed = await env.MY_BUCKET.list({ prefix: 'uploads/' });
// Multipart upload
const multipart = await env.MY_BUCKET.createMultipartUpload('large-file.bin');
const part1 = await multipart.uploadPart(1, chunk1);
const part2 = await multipart.uploadPart(2, chunk2);
await multipart.complete([part1, part2]);
},
};
```
D1 Database
```toml
# wrangler.toml
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-database-id"
```
```typescript
export default {
async fetch(request: Request, env: Env): Promise
// Query
const result = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first();
// Insert
const info = await env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
.bind('Alice', 'alice@example.com')
.run();
// Batch (atomic)
const results = await env.DB.batch([
env.DB.prepare('UPDATE accounts SET balance = balance - 100 WHERE id = ?').bind(1),
env.DB.prepare('UPDATE accounts SET balance = balance + 100 WHERE id = ?').bind(2),
]);
// All results
const { results: rows } = await env.DB.prepare('SELECT * FROM users').all();
return new Response(JSON.stringify(result));
},
};
```
Durable Objects
```toml
# wrangler.toml
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
script_name = "my-worker"
```
```typescript
// Define Durable Object
export class Counter {
state: DurableObjectState;
constructor(state: DurableObjectState, env: Env) {
this.state = state;
}
async fetch(request: Request): Promise
let count = (await this.state.storage.get
count++;
await this.state.storage.put('count', count);
return new Response(JSON.stringify({ count }));
}
// Alarm handler
async alarm(): Promise
// Runs at scheduled time
await this.state.storage.deleteAll();
}
}
// Use in Worker
export default {
async fetch(request: Request, env: Env): Promise
const id = env.COUNTER.idFromName('global');
const counter = env.COUNTER.get(id);
return counter.fetch(request);
},
};
```
Queues
```toml
# wrangler.toml
[[queues.producers]]
binding = "MY_QUEUE"
queue = "my-queue"
[[queues.consumers]]
queue = "my-queue"
max_batch_size = 10
max_batch_timeout = 30
```
```typescript
// Producer
export default {
async fetch(request: Request, env: Env): Promise
await env.MY_QUEUE.send({
type: 'email',
to: 'user@example.com',
});
// Batch send
await env.MY_QUEUE.sendBatch([{ body: { message: 1 } }, { body: { message: 2 } }]);
return new Response('Queued');
},
};
// Consumer
export default {
async queue(batch: MessageBatch, env: Env, ctx: ExecutionContext): Promise
for (const message of batch.messages) {
try {
await processMessage(message.body);
message.ack();
} catch (error) {
message.retry();
}
}
},
};
```
Workers AI
```toml
# wrangler.toml
[ai]
binding = "AI"
```
```typescript
export default {
async fetch(request: Request, env: Env): Promise
// Text generation
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [{ role: 'user', content: 'What is edge computing?' }],
});
// Image generation
const imageResponse = await env.AI.run('@cf/stabilityai/stable-diffusion-xl-base-1.0', {
prompt: 'A sunset over mountains',
});
// Embeddings
const embeddings = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: ['Hello world', 'Cloudflare Workers'],
});
// Speech recognition
const audio = await request.arrayBuffer();
const transcription = await env.AI.run('@cf/openai/whisper', {
audio: [...new Uint8Array(audio)],
});
return new Response(JSON.stringify(response));
},
};
```
Vectorize (Vector Database)
```toml
# wrangler.toml
[[vectorize]]
binding = "VECTORIZE_INDEX"
index_name = "my-index"
```
```typescript
export default {
async fetch(request: Request, env: Env): Promise
// Insert vectors
await env.VECTORIZE_INDEX.insert([
{
id: '1',
values: [0.1, 0.2, 0.3],
metadata: { text: 'Hello world' },
},
]);
// Query
const results = await env.VECTORIZE_INDEX.query([0.1, 0.2, 0.3], { topK: 5 });
return new Response(JSON.stringify(results));
},
};
```
Development Patterns
Routing
```typescript
export default {
async fetch(request: Request): Promise
const url = new URL(request.url);
// Route by path
switch (url.pathname) {
case '/':
return new Response('Home');
case '/about':
return new Response('About');
default:
return new Response('Not Found', { status: 404 });
}
},
};
```
Using Hono framework:
```typescript
import { Hono } from 'hono';
const app = new Hono();
app.get('/', (c) => c.text('Home'));
app.get('/api/users/:id', async (c) => {
const id = c.req.param('id');
const user = await getUser(id);
return c.json(user);
});
export default app;
```
Middleware Pattern
```typescript
async function auth(request: Request, env: Env): Promise
const token = request.headers.get('Authorization');
if (!token) {
return new Response('Unauthorized', { status: 401 });
}
return null; // Continue
}
export default {
async fetch(request: Request, env: Env): Promise
const authResponse = await auth(request, env);
if (authResponse) return authResponse;
// Continue with request
return new Response('Protected content');
},
};
```
Error Handling
```typescript
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise
try {
const response = await processRequest(request, env);
return response;
} catch (error) {
console.error('Error:', error);
// Log to external service
ctx.waitUntil(
fetch('https://logging.example.com/error', {
method: 'POST',
body: JSON.stringify({
error: error.message,
stack: error.stack,
url: request.url,
}),
})
);
return new Response('Internal Server Error', { status: 500 });
}
},
};
```
CORS
```typescript
function corsHeaders(origin: string) {
return {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
};
}
export default {
async fetch(request: Request): Promise
const origin = request.headers.get('Origin') || '*';
// Handle preflight
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: corsHeaders(origin),
});
}
// Handle request
const response = await handleRequest(request);
// Add CORS headers
const headers = new Headers(response.headers);
Object.entries(corsHeaders(origin)).forEach(([key, value]) => {
headers.set(key, value);
});
return new Response(response.body, {
status: response.status,
headers,
});
},
};
```
Rate Limiting
```typescript
async function rateLimit(ip: string, env: Env): Promise
const key = ratelimit:${ip};
const limit = 100;
const window = 60;
const current = await env.MY_KV.get(key);
const count = current ? parseInt(current) : 0;
if (count >= limit) {
return false;
}
await env.MY_KV.put(key, (count + 1).toString(), {
expirationTtl: window,
});
return true;
}
export default {
async fetch(request: Request, env: Env): Promise
const ip = request.headers.get('CF-Connecting-IP') || 'unknown';
if (!(await rateLimit(ip, env))) {
return new Response('Rate limit exceeded', { status: 429 });
}
return new Response('OK');
},
};
```
Testing
Local Testing with Wrangler
```bash
# Start dev server
wrangler dev
# Test with curl
curl http://localhost:8787
# Remote development (uses actual edge)
wrangler dev --remote
```
Unit Testing with Vitest
```bash
npm install -D vitest @cloudflare/vitest-pool-workers
```
vitest.config.ts:
```typescript
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config';
export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
wrangler: { configPath: './wrangler.toml' },
},
},
},
});
```
Test file:
```typescript
import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:test';
import { describe, it, expect } from 'vitest';
import worker from '../src/index';
describe('Worker', () => {
it('responds with Hello World', async () => {
const request = new Request('http://example.com');
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
await waitOnExecutionContext(ctx);
expect(await response.text()).toBe('Hello World!');
});
});
```
Integration Testing
```typescript
import { unstable_dev } from 'wrangler';
describe('Worker integration tests', () => {
let worker;
beforeAll(async () => {
worker = await unstable_dev('src/index.ts', {
experimental: { disableExperimentalWarning: true },
});
});
afterAll(async () => {
await worker.stop();
});
it('should return 200', async () => {
const resp = await worker.fetch();
expect(resp.status).toBe(200);
});
});
```
Deployment
Basic Deployment
```bash
# Deploy to production
wrangler deploy
# Deploy to specific environment
wrangler deploy --env staging
# Preview deployment
wrangler deploy --dry-run
```
Environments
```toml
# wrangler.toml
name = "my-worker"
[env.staging]
name = "my-worker-staging"
routes = [
{ pattern = "staging.example.com/*", zone_name = "example.com" }
]
[env.production]
name = "my-worker-production"
routes = [
{ pattern = "api.example.com/*", zone_name = "example.com" }
]
```
```bash
wrangler deploy --env staging
wrangler deploy --env production
```
CI/CD with GitHub Actions
```yaml
# .github/workflows/deploy.yml
name: Deploy Worker
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install
- run: npm test
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
```
Gradual Deployments
```bash
# Deploy to 10% of traffic
wrangler versions deploy --percentage 10
# Promote to 100%
wrangler versions deploy --percentage 100
# Rollback
wrangler rollback
```
Static Assets
Configuration
```toml
# wrangler.toml
name = "my-worker"
main = "src/index.ts"
[assets]
directory = "./public"
binding = "ASSETS"
```
Serving Static Assets
```typescript
export default {
async fetch(request: Request, env: Env): Promise
// Serve static asset
const asset = await env.ASSETS.fetch(request);
if (asset.status === 200) {
return asset;
}
// Fallback to dynamic response
return new Response('Not Found', { status: 404 });
},
};
```
Single Page Application (SPA)
```toml
[assets]
directory = "./dist"
binding = "ASSETS"
html_handling = "force-https"
not_found_handling = "single-page-application"
```
Observability
Logging
```typescript
export default {
async fetch(request: Request): Promise
console.log('Request URL:', request.url);
console.error('Error occurred');
console.warn('Warning message');
// Structured logging
console.log(
JSON.stringify({
level: 'info',
message: 'Request processed',
url: request.url,
timestamp: new Date().toISOString(),
})
);
return new Response('OK');
},
};
```
Real-time Logs
```bash
# Tail logs
wrangler tail
# Filter by status
wrangler tail --status error
# Filter by method
wrangler tail --method POST
# Filter by sampling
wrangler tail --sampling-rate 0.5
```
Analytics
```typescript
// Use Analytics Engine binding
export default {
async fetch(request: Request, env: Env): Promise
env.ANALYTICS.writeDataPoint({
blobs: ['example'],
doubles: [123.45],
indexes: ['index_value'],
});
return new Response('Logged');
},
};
```
Error Tracking (Sentry)
```typescript
import * as Sentry from '@sentry/cloudflare';
export default {
async fetch(request: Request, env: Env): Promise
Sentry.init({
dsn: env.SENTRY_DSN,
environment: env.ENVIRONMENT,
});
try {
return await handleRequest(request);
} catch (error) {
Sentry.captureException(error);
throw error;
}
},
};
```
Performance Optimization
Best Practices
- Minimize Bundle Size: Keep Workers under 1MB
- Use Bindings: Direct bindings are faster than fetch
- Cache Aggressively: Use Cache API and KV
- Stream Large Responses: Use streams instead of buffering
- Batch Operations: Combine D1 queries with batch()
- waitUntil for Background Tasks: Don't block response
- Avoid Synchronous I/O: All operations should be async
Code Splitting
```typescript
// Lazy load large dependencies
export default {
async fetch(request: Request): Promise
const url = new URL(request.url);
if (url.pathname === '/heavy') {
const { processHeavy } = await import('./heavy');
return processHeavy(request);
}
return new Response('OK');
},
};
```
Caching Strategy
```typescript
const CACHE_TTL = 3600;
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise
const cache = caches.default;
const cacheKey = new Request(request.url);
// 1. Check edge cache
let response = await cache.match(cacheKey);
if (response) return response;
// 2. Check KV cache
const kvCached = await env.MY_KV.get(request.url);
if (kvCached) {
response = new Response(kvCached);
ctx.waitUntil(cache.put(cacheKey, response.clone()));
return response;
}
// 3. Fetch from origin
response = await fetch(request);
// 4. Store in both caches
ctx.waitUntil(
Promise.all([
cache.put(cacheKey, response.clone()),
env.MY_KV.put(request.url, await response.clone().text(), {
expirationTtl: CACHE_TTL,
}),
])
);
return response;
},
};
```
Common Patterns
API Gateway
```typescript
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
const app = new Hono();
app.use('*', cors());
app.use('*', logger());
// Routes
app.get('/api/users', async (c) => {
const users = await c.env.DB.prepare('SELECT * FROM users').all();
return c.json(users.results);
});
app.get('/api/users/:id', async (c) => {
const id = c.req.param('id');
const user = await c.env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(id).first();
if (!user) {
return c.json({ error: 'Not found' }, 404);
}
return c.json(user);
});
app.post('/api/users', async (c) => {
const body = await c.req.json();
const result = await c.env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
.bind(body.name, body.email)
.run();
return c.json({ id: result.meta.last_row_id }, 201);
});
export default app;
```
Authentication
```typescript
import { sign, verify } from 'hono/jwt';
async function authenticate(request: Request, env: Env): Promise
const authHeader = request.headers.get('Authorization');
if (!authHeader?.startsWith('Bearer ')) {
throw new Error('Missing token');
}
const token = authHeader.substring(7);
const payload = await verify(token, env.JWT_SECRET);
return payload;
}
export default {
async fetch(request: Request, env: Env): Promise
try {
const user = await authenticate(request, env);
return new Response(Hello ${user.name});
} catch (error) {
return new Response('Unauthorized', { status: 401 });
}
},
};
```
Image Proxy
```typescript
export default {
async fetch(request: Request): Promise
const url = new URL(request.url);
const imageUrl = url.searchParams.get('url');
if (!imageUrl) {
return new Response('Missing url parameter', { status: 400 });
}
const response = await fetch(imageUrl);
return new Response(response.body, {
headers: {
'Content-Type': response.headers.get('Content-Type') || 'image/jpeg',
'Cache-Control': 'public, max-age=86400',
'CDN-Cache-Control': 'public, max-age=31536000',
},
});
},
};
```
Webhook Handler
```typescript
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise
if (request.method !== 'POST') {
return new Response('Method not allowed', { status: 405 });
}
// Verify signature
const signature = request.headers.get('X-Hub-Signature-256');
const body = await request.text();
const valid = await verifySignature(body, signature, env.WEBHOOK_SECRET);
if (!valid) {
return new Response('Invalid signature', { status: 401 });
}
// Queue for processing
ctx.waitUntil(env.WEBHOOK_QUEUE.send(JSON.parse(body)));
return new Response('OK');
},
};
```
Troubleshooting
Common Issues
CPU Time Exceeded:
- Optimize expensive operations
- Use streams for large data
- Move processing to Durable Objects
- Consider splitting work across multiple requests
Memory Exceeded:
- Stream large responses instead of buffering
- Clear unused variables
- Use chunked processing
Script Size Too Large:
- Remove unused dependencies
- Use code splitting
- Minify production builds
- Check
wrangler deploy --dry-run --outdir=distoutput
Binding Not Found:
- Check wrangler.toml configuration
- Ensure binding name matches env property
- Redeploy after configuration changes
CORS Errors:
- Add proper CORS headers
- Handle OPTIONS requests
- Check allowed origins
Debugging
```bash
# Local debugging
wrangler dev --local
# Remote debugging (real edge environment)
wrangler dev --remote
# Inspect bundle
wrangler deploy --dry-run --outdir=dist
# Check logs
wrangler tail --format pretty
```
Resources
- Main Docs: https://developers.cloudflare.com/workers/
- Examples: https://developers.cloudflare.com/workers/examples/
- Discord: https://discord.cloudflare.com
- GitHub: https://github.com/cloudflare/workers-sdk
- Status: https://www.cloudflarestatus.com
- Pricing: https://developers.cloudflare.com/workers/platform/pricing/
Implementation Checklist
Initial Setup
- [ ] Install Wrangler CLI
- [ ] Login to Cloudflare account
- [ ] Create new Worker project
- [ ] Configure wrangler.toml
- [ ] Test locally with
wrangler dev
Development
- [ ] Implement fetch handler
- [ ] Add error handling
- [ ] Set up TypeScript types
- [ ] Configure bindings (KV, D1, R2, etc.)
- [ ] Add environment variables
- [ ] Implement caching strategy
Testing
- [ ] Write unit tests with Vitest
- [ ] Test locally with wrangler dev
- [ ] Test on remote edge
- [ ] Validate bindings work
Deployment
- [ ] Set up environments (staging, production)
- [ ] Configure routes or custom domains
- [ ] Add secrets
- [ ] Set up CI/CD pipeline
- [ ] Deploy to production
- [ ] Monitor logs and analytics
Production
- [ ] Set up error tracking
- [ ] Configure analytics
- [ ] Implement rate limiting
- [ ] Add monitoring alerts
- [ ] Document API endpoints
- [ ] Set up rollback procedure
More from this repository10
Enables interactive PostgreSQL database management through psql, executing queries, scripting, and administering database operations from the command line.
Provides customizable, accessible React UI components using Tailwind CSS that can be directly copied and modified in your project.
Automates OpenSpec change implementation by parsing tasks, filtering phases, and creating PRs using subagent-driven development.
Enables seamless S3-compatible object storage on Cloudflare's global network with zero egress fees, supporting file uploads, downloads, and migrations.
Securely implement authentication and authorization with a framework-agnostic TypeScript library supporting email/password, OAuth, 2FA, and advanced auth features.
Enables comprehensive MongoDB database management, from schema design and querying to deployment, performance optimization, and secure integration across multiple platforms and languages.
Guides developers in building Vue 3 NuxtUI components using strict Test-Driven Development (TDD) methodology with atomic design principles and Storybook interaction tests.
Accelerates monorepo development by enabling intelligent caching, parallel task execution, and efficient build performance across JavaScript and TypeScript projects.
Generates configurable AI skills with customizable parameters and templates for Claude-based applications.
Translates product requirements into comprehensive UX specifications by systematically analyzing user mental models, information architecture, and interaction design.