Cloudflare Workers: The Complete Guide to Free Tier, Pricing, and Setup

Cloudflare Workers is a serverless platform that runs on Cloudflare’s global edge infrastructure. Instead of deploying code to a fixed server in Virginia or Singapore, Workers execute at the PoP (Point of Presence) closest to your user, delivering extremely low latency without managing servers, containers, or load balancers.

Cloudflare Workers: The Complete Guide to Free Tier, Pricing, and Setup

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

ResourceFree tierNote
Requests100,000 / dayResets daily at 00:00 UTC
CPU time10 ms / invocationRequest is terminated if exceeded
Workers KV — Keys read100,000 / dayRead key-value pairs
Workers KV — Keys written1,000 / dayWrite key-value pairs
Workers KV — Keys deleted1,000 / dayDelete keys
Workers KV — List requests1,000 / dayList keys
Workers KV — Stored data1 GBTotal storage capacity
D1 — Rows read5 million / daySELECT queries
D1 — Rows written100,000 / dayINSERT, UPDATE, DELETE
D1 — Storage5 GBTotal database storage
Workers Logs — Events written200,000 / dayLogs retained for 3 days
Subrequests50 / requestInternal 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

ResourceIncludedOverage fee
Requests10 million / month+$0.30 / million
CPU time30 million ms / month+$0.02 / million ms
Max CPU time / invocation5 minutes (default 30 seconds)
Workers KV — Keys read10 million / month+$0.50 / million
Workers KV — Keys written1 million / month+$5.00 / million
Workers KV — Keys deleted1 million / month+$5.00 / million
Workers KV — List requests1 million / month+$5.00 / million
Workers KV — Stored data1 GB+$0.50 / GB-month
D1 — Rows read25 billion / month+$0.001 / million rows
D1 — Rows written50 million / month+$1.00 / million rows
D1 — Storage5 GB+$0.75 / GB-month
Workers Logs — Events20 million / month+$0.60 / million
Workers Logs — Retention7 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

CostCalculationAmount
Base planFixed$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

CostCalculationAmount
Base planFixed$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-worker

During 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-worker

C3 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 dev

On 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 deploy

If 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.dev

Visit 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_KEY

Enter 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 deploy

Test:

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:123

Step 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 deploy

Hono 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/cloudflare

Add a script to package.json:

"scripts": {
  "build:worker": "opennextjs-cloudflare"
}

Run npm run build:worker then wrangler deploy.

Astro (SSR mode):

npx astro add cloudflare

The @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


  • No comments yet.

Web-Based Tools

Press Ctrl + \ on desktop, or swipe left anywhere on mobile.

Login