What is Cloudflare Workers? (30-Second Explanation)
Cloudflare Workers lets you run JavaScript code on Cloudflare's global network—in 330+ cities worldwide. When someone in Tokyo requests your API, the code runs in Tokyo. Someone in São Paulo? It runs in São Paulo.
🎯 Why Developers Choose Workers
- Zero cold starts — Code starts in under 5ms (Lambda: 500ms-10s)
- Global by default — Deploy once, run everywhere
- Generous free tier — 100,000 requests/day, no credit card needed
- Pay for CPU only — Not billed while waiting on database/API calls
If you've used Express.js, AWS Lambda, or Vercel Edge Functions, you'll feel right at home. The concepts transfer directly.
💡 Real Talk: Teams regularly report reducing API latency from 180ms to under 15ms just by moving from regional cloud to Workers. The code change takes hours. The performance improvement is permanent.
Prerequisites
You'll need:
- Node.js 18+ — Download here
- A Cloudflare account — Sign up free (no credit card required)
- Basic JavaScript knowledge — If you can write a function, you're ready
- A code editor — VS Code recommended
Check your Node.js version:
v20.10.0 ✓
1Install Wrangler CLI
Wrangler is Cloudflare's command-line tool for Workers development. Think of it like create-react-app but for serverless APIs.
Verify installation:
⛅️ wrangler 3.91.0
⚠️ Permission Error on Mac/Linux?
If you get EACCES errors, either use sudo npm install -g wrangler or configure npm to use a different directory. See npm's guide.
2Authenticate with Cloudflare
Connect Wrangler to your Cloudflare account:
This opens your browser. Click "Allow" to authorize Wrangler. You'll see:
Your credentials are stored locally. You only need to do this once per machine.
3Create Your First Worker
Let's create a new project:
When prompted:
- What type of application? → Select
"Hello World" Worker - TypeScript or JavaScript? → Choose
TypeScript(recommended) or JavaScript - Use git? → Yes (recommended)
- Deploy now? → No (we'll explore the code first)
Navigate into your project:
Your project structure:
my-first-worker/
├── src/
│ └── index.ts ← Your Worker code lives here
├── wrangler.toml ← Configuration file
├── package.json
└── tsconfig.json
4Understanding the Code
Open src/index.ts. You'll see something like:
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
return new Response('Hello World!');
},
};
Let's break this down:
🔍 The Anatomy of a Worker
fetch()— The main handler, called for every HTTP requestrequest— The incoming HTTP request (URL, headers, body)env— Environment variables and bindings (KV, D1, R2)ctx— Execution context for background tasksResponse— What you return to the client
If you've used Express.js, this is similar to:
// Express equivalent
app.get('*', (req, res) => {
res.send('Hello World!');
});
The difference? Workers use the standard Web APIs (Request, Response, fetch) that work in browsers. No Express-specific knowledge needed.
5Build a Real API
Let's build something useful: a simple REST API with multiple routes.
Replace your src/index.ts with:
interface Env {
// Add your bindings here (KV, D1, R2, etc.)
}
// Simple in-memory data (use D1 for real apps)
const users = [
{ id: 1, name: 'Alice', city: 'London' },
{ id: 2, name: 'Bob', city: 'Tokyo' },
{ id: 3, name: 'Carlos', city: 'São Paulo' },
];
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const path = url.pathname;
// CORS headers for browser requests
const headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
};
// Route: GET /
if (path === '/' && request.method === 'GET') {
return new Response(JSON.stringify({
message: 'Welcome to my API!',
endpoints: ['/users', '/users/:id', '/health'],
location: request.cf?.city || 'Unknown',
}), { headers });
}
// Route: GET /users
if (path === '/users' && request.method === 'GET') {
return new Response(JSON.stringify(users), { headers });
}
// Route: GET /users/:id
if (path.startsWith('/users/') && request.method === 'GET') {
const id = parseInt(path.split('/')[2]);
const user = users.find(u => u.id === id);
if (!user) {
return new Response(JSON.stringify({ error: 'User not found' }), {
status: 404,
headers,
});
}
return new Response(JSON.stringify(user), { headers });
}
// Route: GET /health
if (path === '/health') {
return new Response(JSON.stringify({
status: 'healthy',
timestamp: new Date().toISOString(),
edge_location: request.cf?.colo || 'Unknown',
}), { headers });
}
// 404 for unknown routes
return new Response(JSON.stringify({ error: 'Not found' }), {
status: 404,
headers,
});
},
};
🌍 Notice request.cf?
Cloudflare automatically adds geo data to every request: city, country, timezone, ASN, and more. This is free and works globally. Perfect for personalization, compliance, and analytics.
6Test Locally
Start the local development server:
You'll see:
Ready on http://localhost:8787
Now test your endpoints:
{"message":"Welcome to my API!","endpoints":["/users","/users/:id","/health"]}
$ curl http://localhost:8787/users
[{"id":1,"name":"Alice","city":"London"},{"id":2,"name":"Bob","city":"Tokyo"},{"id":3,"name":"Carlos","city":"São Paulo"}]
$ curl http://localhost:8787/users/1
{"id":1,"name":"Alice","city":"London"}
Hot reload is automatic. Edit your code, save, and the changes appear instantly. No restart needed.
7Deploy to Production
Ready to go live? One command:
Output:
Published my-first-worker (0.45 sec)
https://my-first-worker.your-subdomain.workers.dev
That's it. Your API is now live on Cloudflare's global network. Try it from your phone, share the URL with a friend in another country—it works everywhere, instantly.
🎉 What Just Happened?
- Your code was bundled and uploaded to Cloudflare
- It's now running in 330+ data centers simultaneously
- Users in Tokyo get served from Tokyo, users in Lagos from Lagos
- Zero configuration, zero DevOps, zero servers to manage
What's Next? Level Up Your Worker
You've built a basic API. Here's how to add real functionality:
🗄️ Add a Database (D1)
SQLite at the edge. Store and query data globally with sub-10ms latency.
wrangler d1 create my-database
Learn D1 →
🔐 Add Authentication
JWT validation, session management, OAuth flows—all at the edge.
Clodo Auth Guide →🤖 Add AI (Workers AI)
Run LLMs, embeddings, and image models directly on the edge. No API keys needed.
const result = await env.AI.run('@cf/meta/llama-2-7b', { prompt: '...' });
📦 Add Storage (R2)
S3-compatible object storage with zero egress fees. Store images, files, backups.
wrangler r2 bucket create my-bucket
5 Common Mistakes to Avoid
1. Using Node.js-specific APIs
Workers use Web APIs, not Node.js APIs. fs, path, process don't exist. Use fetch(), Request, Response instead.
2. Forgetting async/await
All I/O in Workers is async. If you forget await, you'll get [object Promise] instead of actual data.
3. Not handling CORS
Browser requests need CORS headers. Add Access-Control-Allow-Origin to your responses, or handle OPTIONS preflight requests.
4. Blocking the event loop
Workers have a 30-second limit (10ms CPU on free tier). Don't run expensive loops or blocking operations. Use ctx.waitUntil() for background tasks.
5. Hardcoding secrets
Never put API keys in your code. Use wrangler secret put SECRET_NAME and access via env.SECRET_NAME.
Frequently Asked Questions
Is Cloudflare Workers really free?
Yes! The free tier includes 100,000 requests/day, 10ms CPU time per request, and access to Workers KV. Most personal projects and MVPs never exceed this. The paid plan ($5/month) adds 10 million requests and more CPU time.
How does Workers compare to AWS Lambda?
Key differences: Workers start in <5ms (Lambda: 500ms-10s cold starts), run in 330+ cities (Lambda: ~30 regions), and bill only CPU time (Lambda: wall-clock time). For API workloads, Workers is typically 3-10x cheaper with 5-20x better latency.
Can I use npm packages?
Yes, but packages must not rely on Node.js APIs (fs, net, child_process). Most utility libraries work: lodash, date-fns, zod, jose, etc. Cloudflare provides compatibility flags for some Node.js APIs.
How do I connect to my existing database?
Workers can connect to any database with an HTTP API. For traditional databases (PostgreSQL, MySQL), use Cloudflare's Hyperdrive for connection pooling, or D1 for a native edge database.
Can I run Python/Go/Rust?
Workers natively run JavaScript/TypeScript. For other languages, use WebAssembly (Wasm). Rust compiles to Wasm directly. Python via Pyodide. Go via TinyGo. Performance is excellent.
📚 Sources & Further Reading
- Official Cloudflare Workers Documentation — Comprehensive API reference
- Wrangler CLI Documentation — Full command reference
- Workers Examples Gallery — Production-ready code snippets
- Cloudflare Workers: The Infrastructure Revolution — Deep dive into the platform architecture