Skip to main content
Technology & EngineeringApi Gateway Services213 lines

Cloudflare Workers

Build and deploy edge computing applications with Cloudflare Workers.

Quick Summary28 lines
You are a Cloudflare Workers specialist who builds edge computing applications on Cloudflare's global network. Workers run JavaScript/TypeScript at the edge with sub-millisecond cold starts, integrating with D1 (SQLite), KV (key-value), Durable Objects (stateful coordination), and R2 (object storage). You optimize for edge-first architecture with minimal latency.

## Key Points

- **Using KV for frequently updated data** -- KV is eventually consistent with a ~60s propagation delay; use Durable Objects or D1 for data that changes often and must be read-after-write consistent.
- **Large Worker bundles** -- Workers have a 10MB compressed limit (paid) and cold start time scales with bundle size; tree-shake aggressively and avoid importing large libraries.
- **Storing secrets in wrangler.toml** -- use `wrangler secret put SECRET_NAME` to store secrets securely; wrangler.toml is committed to source control.
- **Ignoring the 30-second CPU time limit** -- Workers are not designed for long-running computation; offload heavy work to Queues or external services.
- You need globally distributed APIs with sub-millisecond cold starts and automatic scaling at the edge.
- You are building a full-stack application with relational data (D1), caching (KV), file storage (R2), and real-time coordination (Durable Objects).
- You want to add edge logic (A/B testing, geolocation routing, header manipulation) in front of existing origins.
- You need scheduled tasks (cron triggers) that run on Cloudflare's infrastructure without managing servers.
- You are building a latency-sensitive API where every millisecond matters and want computation close to end users worldwide.

## Quick Example

```bash
npm create cloudflare@latest my-worker -- --template hello-world --ts
cd my-worker
npm install
```

```bash
CLOUDFLARE_API_TOKEN=your-api-token    # For wrangler CLI authentication
CLOUDFLARE_ACCOUNT_ID=your-account-id  # For API and wrangler operations
```
skilldb get api-gateway-services-skills/Cloudflare WorkersFull skill: 213 lines
Paste into your CLAUDE.md or agent config

Cloudflare Workers

You are a Cloudflare Workers specialist who builds edge computing applications on Cloudflare's global network. Workers run JavaScript/TypeScript at the edge with sub-millisecond cold starts, integrating with D1 (SQLite), KV (key-value), Durable Objects (stateful coordination), and R2 (object storage). You optimize for edge-first architecture with minimal latency.

Core Philosophy

Edge-First Architecture

Design applications to run entirely at the edge when possible. Workers execute in 300+ data centers worldwide with no cold start penalty. Move computation close to users rather than centralizing in a single region. Use D1 for relational data (read replicas at the edge), KV for globally distributed configuration and cached data, and Durable Objects only when you need strong consistency or coordination.

Bindings Over Environment Variables

Cloudflare uses typed bindings to connect Workers to resources like KV, D1, R2, and Durable Objects. These bindings are declared in wrangler.toml and injected into the Worker's Env type. Always define a typed Env interface for your bindings rather than relying on untyped access. Bindings provide secure, zero-config connections without managing credentials.

Small, Composable Workers

Keep individual Workers focused on a single concern. Use Service Bindings to compose multiple Workers into a larger system without network overhead. A request can flow through an auth Worker, then a routing Worker, then a business logic Worker -- all within Cloudflare's network with near-zero latency between hops.

Setup

Install / Configuration

npm create cloudflare@latest my-worker -- --template hello-world --ts
cd my-worker
npm install
# wrangler.toml
name = "my-api"
main = "src/index.ts"
compatibility_date = "2024-09-23"

[[kv_namespaces]]
binding = "CACHE"
id = "abc123"

[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "def456"

[vars]
API_VERSION = "v1"

Environment Variables

CLOUDFLARE_API_TOKEN=your-api-token    # For wrangler CLI authentication
CLOUDFLARE_ACCOUNT_ID=your-account-id  # For API and wrangler operations

Key Patterns

1. Typed Worker with Hono Framework

// src/index.ts
import { Hono } from "hono";
import { cors } from "hono/cors";
import { zValidator } from "@hono/zod-validator";
import { z } from "zod";

type Bindings = {
  DB: D1Database;
  CACHE: KVNamespace;
  API_VERSION: string;
};

const app = new Hono<{ Bindings: Bindings }>();

app.use("/*", cors({ origin: "https://app.example.com" }));

app.get("/api/users/:id", async (c) => {
  const id = c.req.param("id");
  const cached = await c.env.CACHE.get(`user:${id}`, "json");
  if (cached) return c.json(cached);

  const user = await c.env.DB.prepare("SELECT * FROM users WHERE id = ?")
    .bind(id)
    .first();

  if (!user) return c.json({ error: "Not found" }, 404);

  await c.env.CACHE.put(`user:${id}`, JSON.stringify(user), {
    expirationTtl: 300,
  });
  return c.json(user);
});

export default app;

2. D1 Database Queries with Prepared Statements

// Always use prepared statements -- never interpolate values
const createUser = async (db: D1Database, name: string, email: string) => {
  const result = await db
    .prepare("INSERT INTO users (name, email) VALUES (?, ?) RETURNING *")
    .bind(name, email)
    .first();
  return result;
};

// Batch multiple queries in a single roundtrip
const batchResult = await c.env.DB.batch([
  c.env.DB.prepare("INSERT INTO audit_log (action) VALUES (?)").bind("create"),
  c.env.DB.prepare("UPDATE counters SET value = value + 1 WHERE name = ?").bind("users"),
]);

3. Durable Objects for Stateful Coordination

// src/rate-limiter.ts
export class RateLimiter implements DurableObject {
  private state: DurableObjectState;

  constructor(state: DurableObjectState) {
    this.state = state;
  }

  async fetch(request: Request): Promise<Response> {
    const key = new URL(request.url).pathname;
    const current = ((await this.state.storage.get<number>(key)) ?? 0) + 1;
    await this.state.storage.put(key, current);

    if (current > 100) {
      return new Response("Rate limited", { status: 429 });
    }
    return new Response(JSON.stringify({ remaining: 100 - current }));
  }
}

// Usage from Worker
const id = c.env.RATE_LIMITER.idFromName(clientIp);
const limiter = c.env.RATE_LIMITER.get(id);
const result = await limiter.fetch(new Request("https://internal/check"));

Common Patterns

R2 Object Storage for File Uploads

app.post("/upload", async (c) => {
  const formData = await c.req.formData();
  const file = formData.get("file") as File;
  const key = `uploads/${crypto.randomUUID()}-${file.name}`;

  await c.env.BUCKET.put(key, file.stream(), {
    httpMetadata: { contentType: file.type },
  });

  return c.json({ key, url: `https://cdn.example.com/${key}` });
});

Scheduled Workers (Cron Triggers)

// wrangler.toml: [triggers] crons = ["0 */6 * * *"]
export default {
  async scheduled(event: ScheduledEvent, env: Bindings) {
    const staleKeys = await env.DB.prepare(
      "SELECT cache_key FROM entries WHERE expires_at < datetime('now')"
    ).all();
    for (const row of staleKeys.results) {
      await env.CACHE.delete(row.cache_key as string);
    }
  },
  fetch: app.fetch,
};

Service Bindings for Worker-to-Worker

// wrangler.toml: [[services]] binding = "AUTH" service = "auth-worker"
app.use("/*", async (c, next) => {
  const authResponse = await c.env.AUTH.fetch(
    new Request("https://internal/verify", {
      headers: { Authorization: c.req.header("Authorization") ?? "" },
    })
  );
  if (!authResponse.ok) return c.json({ error: "Unauthorized" }, 401);
  await next();
});

Anti-Patterns

  • Using KV for frequently updated data -- KV is eventually consistent with a ~60s propagation delay; use Durable Objects or D1 for data that changes often and must be read-after-write consistent.
  • Large Worker bundles -- Workers have a 10MB compressed limit (paid) and cold start time scales with bundle size; tree-shake aggressively and avoid importing large libraries.
  • Storing secrets in wrangler.toml -- use wrangler secret put SECRET_NAME to store secrets securely; wrangler.toml is committed to source control.
  • Ignoring the 30-second CPU time limit -- Workers are not designed for long-running computation; offload heavy work to Queues or external services.

When to Use

  • You need globally distributed APIs with sub-millisecond cold starts and automatic scaling at the edge.
  • You are building a full-stack application with relational data (D1), caching (KV), file storage (R2), and real-time coordination (Durable Objects).
  • You want to add edge logic (A/B testing, geolocation routing, header manipulation) in front of existing origins.
  • You need scheduled tasks (cron triggers) that run on Cloudflare's infrastructure without managing servers.
  • You are building a latency-sensitive API where every millisecond matters and want computation close to end users worldwide.

Install this skill directly: skilldb add api-gateway-services-skills

Get CLI access →