← All articles
CLOUD Cloudflare Workers: Edge Functions for JavaScript De... 2026-03-04 · 4 min read · cloudflare · workers · edge computing

Cloudflare Workers: Edge Functions for JavaScript Developers

Cloud 2026-03-04 · 4 min read cloudflare workers edge computing serverless wrangler kv storage typescript javascript

Cloudflare Workers runs your JavaScript or TypeScript at the network edge — in 300+ data centers worldwide, milliseconds from any user. Unlike AWS Lambda (regional) or traditional servers (centralized), Workers execute at the location closest to the incoming request. This guide covers what Workers is, how to develop with it, and where it makes sense.

What Workers Is (and Isn't)

What it is:

What it isn't:

Getting Started

Install Wrangler (Workers CLI):

npm install -g wrangler
# or
bun add -g wrangler

Create a new project:

wrangler init my-worker
cd my-worker

This generates a wrangler.toml and a TypeScript worker:

// src/index.ts
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    return new Response("Hello World!");
  },
} satisfies ExportedHandler<Env>;

Deploy:

wrangler deploy

Local development:

wrangler dev

wrangler dev runs a local server that closely emulates the Workers runtime, including KV, R2, and D1 bindings.

Request/Response Model

Workers use the standard Web Request and Response APIs:

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);

    // Route handling
    if (url.pathname === "/api/hello") {
      return Response.json({ message: "Hello from the edge!" });
    }

    if (request.method === "POST" && url.pathname === "/api/data") {
      const body = await request.json();
      // process body...
      return Response.json({ received: body }, { status: 201 });
    }

    return new Response("Not Found", { status: 404 });
  },
};

KV Storage

Workers KV is a global key-value store with eventual consistency. Data written in one region propagates worldwide within seconds.

Create a KV namespace:

wrangler kv:namespace create "MY_KV"

Add the binding in wrangler.toml:

[[kv_namespaces]]
name = "MY_KV"
id = "your-namespace-id"

Use it in your worker:

interface Env {
  MY_KV: KVNamespace;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // Write
    await env.MY_KV.put("user:1", JSON.stringify({ name: "Alice" }), {
      expirationTtl: 86400  // expire after 1 day
    });

    // Read
    const user = await env.MY_KV.get("user:1", "json");

    // List keys
    const list = await env.MY_KV.list({ prefix: "user:" });

    return Response.json(user);
  },
};

KV limits and use cases:

R2 Object Storage

R2 is S3-compatible object storage with no egress fees. Access from Workers:

interface Env {
  MY_BUCKET: R2Bucket;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const key = new URL(request.url).pathname.slice(1);

    if (request.method === "GET") {
      const object = await env.MY_BUCKET.get(key);
      if (!object) return new Response("Not found", { status: 404 });
      return new Response(object.body, {
        headers: { "Content-Type": object.httpMetadata?.contentType ?? "application/octet-stream" }
      });
    }

    if (request.method === "PUT") {
      await env.MY_BUCKET.put(key, request.body);
      return new Response("Uploaded", { status: 201 });
    }

    return new Response("Method not allowed", { status: 405 });
  },
};

D1: SQLite at the Edge

D1 is Cloudflare's serverless SQLite database, directly accessible from Workers:

wrangler d1 create my-db
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "your-db-id"
interface Env {
  DB: D1Database;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const { results } = await env.DB.prepare(
      "SELECT * FROM users WHERE id = ?"
    ).bind(1).all();

    return Response.json(results);
  },
};

D1 supports migrations, and you can run queries locally via wrangler d1 execute.

Durable Objects

Durable Objects provide stateful, singleton JavaScript objects with built-in storage. Each Durable Object has a unique ID and runs in exactly one location. Useful for: real-time collaboration, WebSocket hubs, rate limiting, transactional state.

export class Counter implements DurableObject {
  private state: DurableObjectState;
  private count = 0;

  constructor(state: DurableObjectState) {
    this.state = state;
    // Restore persisted state
    this.state.blockConcurrencyWhile(async () => {
      this.count = (await this.state.storage.get<number>("count")) ?? 0;
    });
  }

  async fetch(request: Request): Promise<Response> {
    this.count++;
    await this.state.storage.put("count", this.count);
    return Response.json({ count: this.count });
  }
}

Workers AI

Run ML inference at the edge using Cloudflare's GPU network:

interface Env {
  AI: Ai;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const response = await env.AI.run("@cf/meta/llama-3.1-8b-instruct", {
      messages: [{ role: "user", content: "Summarize this text..." }]
    });

    return Response.json(response);
  },
};

Available models include Llama 3, Mistral, Stable Diffusion, Whisper, and text embedding models.

Routing with Hono

Hono is a lightweight web framework built for edge runtimes. The standard choice for Workers with complex routing:

bun add hono
import { Hono } from "hono";

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

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();
  return c.json(user);
});

app.post("/api/users", async (c) => {
  const body = await c.req.json();
  // create user...
  return c.json({ created: true }, 201);
});

export default app;

When Workers Makes Sense

Good fits:

Poor fits:

Pricing

Free Paid ($5/month base)
Requests 100K/day 10M/month included
CPU time 10ms 30s
KV reads 100K/day 10M/month
KV writes 1K/day 1M/month

For most hobby projects and low-traffic APIs, the free tier is sufficient. Worker pricing scales predictably — $0.50 per million requests beyond the included amount.

Local Development Workflow

# Start dev server with all bindings emulated locally
wrangler dev

# Run type checking
tsc --noEmit

# Deploy to preview (non-production)
wrangler deploy --env preview

# View logs in real-time
wrangler tail

Workers integrates with GitHub Actions for CI/CD:

- name: Deploy Worker
  uses: cloudflare/wrangler-action@v3
  with:
    apiToken: ${{ secrets.CF_API_TOKEN }}