- How Far Does the Cloudflare Workers Free Tier Go?
- Daily and monthly free tier limits
- How Cloudflare Workers Pricing Works in Detail
- Workers Paid plan pricing table
- How is CPU time calculated?
- Real-world cost examples
- Step-by-Step Cloudflare Workers Setup Guide
- Requirements
- Step 1: Install C3 and create a project
- Step 2: Understand the wrangler.jsonc file structure
- Step 3: Write your first Worker code
- Step 4: Run locally with Wrangler dev
- Step 5: Deploy to production
- Step 6: Add environment variables
- Step 7: Connect with Workers KV
- Step 8: Integration with popular frameworks
- Important Things to Remember When Using Workers
- Conclusion
In this guide, we will cover every practical aspect: how far the free tier actually goes, how Cloudflare bills you when you exceed limits, and a step-by-step project setup from scratch with working code you can run immediately on localhost and production.
How Far Does the Cloudflare Workers Free Tier Go?
The Workers free tier has no expiration date. Unlike AWS Lambda (free for only the first 12 months), you can use Workers for free forever as long as you stay within the limits.
Daily and monthly free tier limits
| Resource | Free tier | Note |
|---|---|---|
| Requests | 100,000 / day | Resets daily at 00:00 UTC |
| CPU time | 10 ms / invocation | Request is terminated if exceeded |
| Workers KV — Keys read | 100,000 / day | Read key-value pairs |
| Workers KV — Keys written | 1,000 / day | Write key-value pairs |
| Workers KV — Keys deleted | 1,000 / day | Delete keys |
| Workers KV — List requests | 1,000 / day | List keys |
| Workers KV — Stored data | 1 GB | Total storage capacity |
| D1 — Rows read | 5 million / day | SELECT queries |
| D1 — Rows written | 100,000 / day | INSERT, UPDATE, DELETE |
| D1 — Storage | 5 GB | Total database storage |
| Workers Logs — Events written | 200,000 / day | Logs retained for 3 days |
| Subrequests | 50 / request | Internal requests from Worker to external APIs |
How are requests counted? Every incoming request to your Worker counts as one. Cloudflare does not charge for subrequests (requests your Worker makes to external APIs). The initial WebSocket connection counts as one request, but subsequent messages over the WebSocket are not counted. Requests for static assets are also free and unlimited.
What can you do within 10 ms of CPU time?
- API proxy, redirect, URL rewrite.
- JWT authentication middleware, header checks.
- Simple A/B testing.
- Webhook handler receiving and processing small payloads.
- Edge rendering of static HTML or simple JSON responses.
If you need heavier processing, such as image resizing, parsing large files, or running machine learning inference, 10 ms will not be enough and you will need to upgrade to a paid plan.
How Cloudflare Workers Pricing Works in Detail
The paid plan has a minimum charge of $5/month, which includes a certain amount of usage. You are only billed extra when you exceed those included amounts.
Workers Paid plan pricing table
| Resource | Included | Overage fee |
|---|---|---|
| Requests | 10 million / month | +$0.30 / million |
| CPU time | 30 million ms / month | +$0.02 / million ms |
| Max CPU time / invocation | 5 minutes (default 30 seconds) | |
| Workers KV — Keys read | 10 million / month | +$0.50 / million |
| Workers KV — Keys written | 1 million / month | +$5.00 / million |
| Workers KV — Keys deleted | 1 million / month | +$5.00 / million |
| Workers KV — List requests | 1 million / month | +$5.00 / million |
| Workers KV — Stored data | 1 GB | +$0.50 / GB-month |
| D1 — Rows read | 25 billion / month | +$0.001 / million rows |
| D1 — Rows written | 50 million / month | +$1.00 / million rows |
| D1 — Storage | 5 GB | +$0.75 / GB-month |
| Workers Logs — Events | 20 million / month | +$0.60 / million |
| Workers Logs — Retention | 7 days |
How is CPU time calculated?
CPU time is different from wall-clock time (actual elapsed time). If your Worker waits 2 seconds for an external API response, that waiting time does not count toward CPU time. Only the time the CPU actually spends processing your logic is counted.
Example: A Worker processes requests with an average of 7 ms CPU, serving 15 million requests per month.
- Requests: (15M – 10M free) x $0.30/million = $1.50
- CPU time: 15M x 7ms = 105 million ms. (105M – 30M free) x $0.02/million = $1.50
- Total: $5 (base) + $1.50 + $1.50 = $8.00/month
Real-world cost examples
Scenario 1: Small API, 500K requests/month, light CPU
| Cost | Calculation | Amount |
|---|---|---|
| Base plan | Fixed | $5.00 |
| Requests (500K) | Under 10M, within included | $0 |
| CPU time (approx. 3M ms) | Under 30M, within included | $0 |
| Total | $5.00/month |
Scenario 2: Medium SaaS, 50M requests/month, average 5 ms CPU
| Cost | Calculation | Amount |
|---|---|---|
| Base plan | Fixed | $5.00 |
| Requests (50M) | (50M – 10M) x $0.30/million | $12.00 |
| CPU time (250M ms) | (250M – 30M) x $0.02/million | $4.40 |
| Total | $21.40/month |
Comparison with AWS Lambda: For 50M requests, Lambda could cost hundreds of dollars in request fees and compute charges alone. Workers, with its $0.30/million request pricing and CPU time billing instead of duration billing, is often significantly cheaper for HTTP-first workloads.
Step-by-Step Cloudflare Workers Setup Guide
Below is a complete, up-to-date guide based on Wrangler v4 and C3 (create-cloudflare-cli). You will create a project, run it locally, and deploy to production within 10 minutes.
Requirements
- Node.js 20 or later (recommended to use nvm for version management).
- A Cloudflare account (free).
Step 1: Install C3 and create a project
C3 (create-cloudflare-cli) is Cloudflare’s official scaffolding tool. Open your terminal and run:
npm create cloudflare@latest -- my-first-workerDuring setup, select the following options:
- What would you like to start with? Hello World example
- Which template would you like to use? Worker only
- Which language do you want to use? JavaScript (or TypeScript if you prefer)
- Do you want to use git for version control? Yes
- Do you want to deploy your application? No (we will edit before deploying)
After completion, enter the project directory:
cd my-first-workerC3 will generate the following files:
wrangler.jsonc— Wrangler configuration file (JSON with comments format).src/index.js— Worker entry point.package.json— Dependencies.
Step 2: Understand the wrangler.jsonc file structure
This file is the single source of truth for deployment configuration. Default contents:
{
"name": "my-first-worker",
"compatibility_date": "2026-07-01",
"main": "src/index.js"
}Important fields:
name: Worker name, must be unique within your account.compatibility_date: Determines the runtime API version. Always use the latest date when deploying to production.main: Application entry point.
If your project needs Node.js APIs (for example, when using Next.js or some frameworks), add:
{
"name": "my-first-worker",
"compatibility_date": "2026-07-01",
"compatibility_flags": ["nodejs_compat"],
"main": "src/index.js"
}Step 3: Write your first Worker code
Open src/index.js and replace it with the following code:
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Simple routing
if (url.pathname === "/") {
return new Response("Hello from Cloudflare Workers!", {
headers: { "content-type": "text/plain" },
});
}
if (url.pathname === "/api/time") {
return Response.json({
timestamp: Date.now(),
iso: new Date().toISOString(),
region: request.cf?.colo || "unknown",
});
}
if (url.pathname === "/api/echo" && request.method === "POST") {
const body = await request.json();
return Response.json({
received: body,
method: request.method,
headers: Object.fromEntries(request.headers),
});
}
return new Response("Not Found", { status: 404 });
},
};This code creates three endpoints:
GET /— Returns simple text.GET /api/time— Returns timestamp and edge region (colo).POST /api/echo— Echoes back the received JSON body.
Step 4: Run locally with Wrangler dev
In the project directory, run:
npx wrangler devOn the first run, Wrangler will ask you to log in. Open your browser, sign in to Cloudflare, and select Allow. Wrangler will then provide a local URL (usually http://localhost:8787).
Test in another terminal:
curl http://localhost:8787/
curl http://localhost:8787/api/time
curl -X POST http://localhost:8787/api/echo \
-H "Content-Type: application/json" \
-d '{"name":"Cloudflare","type":"Workers"}'If the output is correct, you are ready to deploy.
Step 5: Deploy to production
Run the command:
npx wrangler deployIf this is your first deployment, Wrangler will ask if you want to create a workers.dev subdomain. Select Yes and enter a subdomain name (for example yourname). Your Worker will then be available at:
https://my-first-worker.yourname.workers.devVisit that URL in your browser or test with curl. If you see a 523 error on the first attempt, wait about one minute for DNS propagation.
Step 6: Add environment variables
In wrangler.jsonc, add a vars section:
{
"name": "my-first-worker",
"compatibility_date": "2026-07-01",
"main": "src/index.js",
"vars": {
"ENVIRONMENT": "production",
"API_VERSION": "v1"
}
}In your code, access them via env.VAR_NAME:
export default {
async fetch(request, env, ctx) {
return Response.json({
environment: env.ENVIRONMENT,
version: env.API_VERSION,
});
},
};Security note: Variables in wrangler.jsonc are not encrypted and are visible in the dashboard. For API keys and secret tokens, use Wrangler Secrets:
npx wrangler secret put API_KEYEnter the value when prompted. Secrets are encrypted and can only be accessed via env.API_KEY at runtime.
Step 7: Connect with Workers KV
Workers KV is a global key-value store suitable for configuration, caching, and session data.
Create a KV namespace:
npx wrangler kv namespace create "MY_KV"Copy the output id and add it to wrangler.jsonc:
{
"name": "my-first-worker",
"compatibility_date": "2026-07-01",
"main": "src/index.js",
"kv_namespaces": [
{
"binding": "MY_KV",
"id": "your-kv-namespace-id-here"
}
]
}Code using KV:
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === "/kv/set" && request.method === "POST") {
const { key, value } = await request.json();
await env.MY_KV.put(key, value);
return Response.json({ status: "saved", key });
}
if (url.pathname.startsWith("/kv/get/")) {
const key = url.pathname.split("/")[3];
const value = await env.MY_KV.get(key);
return value
? Response.json({ key, value })
: new Response("Not found", { status: 404 });
}
return new Response("Not Found", { status: 404 });
},
};Redeploy:
npx wrangler deployTest:
curl -X POST https://my-first-worker.yourname.workers.dev/kv/set \
-H "Content-Type: application/json" \
-d '{"key":"user:123","value":"{\"name\":\"Alice\"}"}'
curl https://my-first-worker.yourname.workers.dev/kv/get/user:123Step 8: Integration with popular frameworks
Hono (recommended for APIs and microservices):
npm create hono@latest my-hono-app
# Select template: cloudflare-workers
cd my-hono-app
npm install
npx wrangler deployHono runs natively on the Workers runtime without needing an adapter.
Next.js (via OpenNext adapter):
npx create-next-app@latest my-next-app
cd my-next-app
npm install @opennextjs/cloudflareAdd a script to package.json:
"scripts": {
"build:worker": "opennextjs-cloudflare"
}Run npm run build:worker then wrangler deploy.
Astro (SSR mode):
npx astro add cloudflareThe @astrojs/cloudflare adapter will auto-configure. Build and deploy with wrangler pages deploy dist.
Important Things to Remember When Using Workers
- The free tier is calculated daily, not monthly. 100K requests per day means you could use up to 3 million requests per month for free if evenly distributed. But if one day spikes to 150K, the extra 50K requests will be rejected (or require an upgrade to paid).
- 10 ms CPU time on the free tier is very restrictive. Parsing large JSON, complex regex, or heavy loops can easily exceed the limit. If you see error 1101 (Worker exceeded CPU time), that is a sign you need the paid plan.
- There are no egress fees. Data transfer out from Workers is completely free. This is a major advantage over AWS Lambda.
- Workers KV is eventually consistent. Data written to KV may take a few seconds to propagate globally. Do not use KV for data requiring immediate strong consistency. In those cases, use D1 or Durable Objects.
- Subrequests are limited to 50 per request on the free tier. If your Worker calls many external APIs, optimize with batch requests or use Service Bindings (calling another Worker in the same account is free).
- Workers Logs are free but retained for only 3 days. If you need longer retention, use Workers Logpush (paid only) or send logs to an external service.
Conclusion
Cloudflare Workers is one of the most accessible serverless platforms for developers today. The free tier of 100K requests per day plus 10 ms CPU time is enough to run a small API, middleware, webhook handler, or even a static site generator. The paid plan starts at just $5/month with 10 million requests included and unlimited egress, making it highly competitive against AWS Lambda and Google Cloud Functions.
The real strength of Workers is not just the low price, but zero-millisecond cold starts on global edge infrastructure. Your code runs at the point closest to the user without configuring regions, load balancers, or auto-scaling.
Start by running npm create cloudflare@latest, write a simple endpoint, test it locally with wrangler dev, and deploy to workers.dev within 5 minutes. From there, you can expand with KV, D1, R2, Queues, and Durable Objects to build a complete full-stack application without managing a single server.

Comments