🌏 中文版
Cloudflare Workers is often compared to AWS Lambda, but the two have fundamentally different architectures. Lambda runs in containers; Workers runs in V8 Isolates. That single difference shapes everything.
V8 Isolates vs. Containers
Lambda’s cold start problem is essentially the cost of container startup: pulling an image, allocating resources, booting the runtime — best case a few hundred milliseconds, worst case several seconds.
Workers uses V8 Isolates — the same engine that runs JavaScript in Chrome. Isolates are memory-isolated from each other but share the same V8 engine, so there’s no new process or container to spin up. Startup time sits between 0–5ms. When Cloudflare claims “no cold starts,” it’s not marketing — it’s architecturally true.
The other key difference is where code runs. Lambda executes in the AWS region you choose; Workers is automatically deployed to Cloudflare’s 300+ global PoPs. A request from Taiwan gets handled at a nearby edge node — no round-tripping across the globe.
Limitations Up Front
Workers isn’t a silver bullet. The constraints are hard:
- CPU time: 10ms on the free tier, 30ms on paid (extendable to 5 minutes via
ctx.waitUntil()) - Memory: 128MB per Worker
- Request duration: 30 seconds max per request (subrequests have separate limits)
- No native Node.js APIs:
fs,net,child_processare unavailable — though most pure-JS packages work fine - Not for long-running work: batch jobs, scheduled crawlers, video transcoding are all poor fits
The Workers runtime is built on the Service Worker API plus a subset of Web APIs — it’s not a full Node.js environment. Some Node.js built-ins like node:crypto and node:buffer are available via compatibility flags, but you have to explicitly opt in.
The Simplest Possible Worker
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === "/") {
return new Response("Hello from the edge", { status: 200 });
}
return new Response("Not found", { status: 404 });
},
};
env is where Bindings come in — more on that below.
Building an API with Hono
Writing a full API with raw fetch handlers gets tedious fast — you end up rolling your own routing. Hono is a Web framework designed specifically for edge runtimes: tiny bundle size, native support for the Workers API.
import { Hono } from "hono";
import { cors } from "hono/cors";
type Bindings = {
DB: D1Database;
KV: KVNamespace;
AI: Ai;
};
const app = new Hono<{ Bindings: Bindings }>();
app.use("*", cors());
app.get("/api/posts", async (c) => {
const posts = await c.env.DB.prepare(
"SELECT id, title, created_at FROM posts ORDER BY created_at DESC LIMIT 20"
).all();
return c.json(posts.results);
});
app.post("/api/posts", async (c) => {
const body = await c.req.json<{ title: string; content: string }>();
const result = await c.env.DB.prepare(
"INSERT INTO posts (title, content) VALUES (?, ?)"
)
.bind(body.title, body.content)
.run();
return c.json({ id: result.meta.last_row_id }, 201);
});
export default app;
c.env gives you type-safe access to your Workers Bindings, with full IDE autocomplete.
The wrangler CLI
wrangler is Cloudflare’s official developer tool, covering everything from project initialization to production deployment.
# Install
npm install -g wrangler
# Authenticate
wrangler login
# Local development (simulates the Workers environment)
wrangler dev
# Deploy
wrangler deploy
# Stream live logs
wrangler tail
wrangler dev starts a local server that simulates the Workers runtime. Bindings (D1, KV, R2) can point to either local emulators or real Cloudflare resources — switch between them with --remote.
wrangler.toml is your configuration file:
name = "my-api"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
[[kv_namespaces]]
binding = "KV"
id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
[ai]
binding = "AI"
The Bindings System
Bindings are how Workers connects to Cloudflare services. They’re injected via the env object — no API keys required, no network overhead (inside a Worker, a Binding is a direct runtime connection).
Key Bindings:
| Binding | Purpose |
|---|---|
D1Database | SQLite relational database |
KVNamespace | Key-value store, ideal for caching |
R2Bucket | Object storage, S3-compatible |
Ai | Workers AI — embeddings and LLMs |
Queue | Message queue for async job processing |
DurableObjectNamespace | Stateful single-instance objects |
Fetcher | Service binding to call another Worker |
Cloudflare KV is eventually consistent — global reads are fast but writes have propagation delay. Cloudflare R2 is the right choice for static assets and user-uploaded media, with no egress fees.
Pricing
Free tier:
- 100,000 requests per day
- CPU time: 10ms per request
- KV, D1, and R2 each include a free usage quota
Paid tier (Workers Paid, $5/month):
- 10,000,000 requests per month (additional at $0.30 per million)
- CPU time raised to 30ms, extendable
- Significantly higher D1, KV, and R2 quotas
The free tier covers most side projects and small-to-medium applications. At $5/month, Workers Paid is one of the cheapest serverless options in the industry — equivalent Lambda + API Gateway setups cost considerably more.
How NobodyClimb Uses Workers
NobodyClimb runs its entire backend on Workers with no traditional server:
- Web SSR: Next.js 15 deployed to Workers via @opennextjs/cloudflare — dynamic routes handled by Workers, static assets served via Cloudflare Assets
- API: A Hono Worker connected to D1 (user data, climbing records) and KV (caching, rate limiting)
- AI: The RAG Pipeline also runs in Workers — embeddings and LLM calls go through
env.AIvia Workers AI
The core reasoning: a climbing community platform has unpredictable traffic. Running a persistent server wastes money when traffic is low. Workers bills per request — idle time costs nothing, and when traffic spikes, it responds fast from the nearest edge node worldwide.
When to Use Workers — and When Not To
Good fits for Workers:
- REST APIs, GraphQL endpoints
- SSR with Next.js, Nuxt, or similar adapters
- Edge middleware (auth, redirects, A/B testing)
- Webhook handlers
- Lightweight scheduled tasks (via Cron Triggers)
Poor fits for Workers:
- Tasks running longer than 30 seconds (video processing, large batch jobs)
- Heavy CPU-bound workloads (ML training, image processing)
- Packages that depend on native Node.js APIs (some database drivers, native addons)
- Persistent WebSocket connections (Durable Objects can help, but complexity increases)
- Anything requiring a local filesystem (
fsis unavailable)
Compared to traditional VPS or container setups: Workers trades execution flexibility (time limits, memory caps, API restrictions) for zero infrastructure management, global deployment, and very cheap billing. If your application fits within those constraints, Workers is an excellent choice. If it doesn’t, use containers.
References
Loading...