Skip to main content

Cloudflare Workers: Limits, Pricing & Optimization Guide

Cloudflare Workers run JavaScript and WebAssembly at 300+ global edge locations with near-zero cold starts. Understanding the limits — CPU time, memory, storage quotas, and subrequest counts — is essential for production deployments.

✓ Free vs Paid plan comparison ✓ KV / R2 / D1 / Queue limits ✓ CPU optimization techniques ✓ Workers vs Durable Objects

Workers Plans: Free vs Paid Limits

Limit Free Plan Paid Plan ($5/mo)
Requests/day100,00010M/month included
CPU time/request10ms50ms (30ms free, then $0.02/M CPU-ms)
Memory/Worker128MB128MB
Script size1MB compressed10MB compressed
Subrequests/request501,000
KV reads/day100,00010M/month
KV writes/day1,0001M/month
Cron triggersNot availableIncluded

Storage Options: KV vs R2 vs D1 vs Queue

Service Type Max Value Size Consistency Best For
Workers KVKey-Value25MBEventualConfig, feature flags
R2Object Storage5TBStrongFiles, images, data
D1SQLite DB2GB/DBStrongRelational data
QueuesMessage Queue128KB/msgAt-least-onceBackground jobs

A Basic Cloudflare Worker with KV and D1

// Worker with KV and D1 bindings (wrangler.toml)
// [[kv_namespaces]]
// binding = "CACHE"
// id = "abc123"
// [[d1_databases]]
// binding = "DB"
// database_id = "def456"

export interface Env {
  CACHE: KVNamespace;
  DB: D1Database;
}

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

    // Check KV cache first (fast edge read)
    const cached = await env.CACHE.get(`user:${userId}`);
    if (cached) {
      return Response.json(JSON.parse(cached), {
        headers: { 'X-Cache': 'HIT' }
      });
    }

    // Fall through to D1 (SQLite at edge)
    const { results } = await env.DB.prepare(
      'SELECT * FROM users WHERE id = ?'
    ).bind(userId).all();

    if (results.length === 0) {
      return new Response('Not found', { status: 404 });
    }

    // Cache result for 60 seconds
    await env.CACHE.put(
      `user:${userId}`,
      JSON.stringify(results[0]),
      { expirationTtl: 60 }
    );

    return Response.json(results[0], {
      headers: { 'X-Cache': 'MISS' }
    });
  }
};

Handling CPU-Intensive Work

If your workload exceeds the 50ms CPU limit, use these strategies:

// Strategy 1: Use waitUntil() for non-blocking background work
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    // Return response immediately
    const response = new Response('Accepted', { status: 202 });

    // Process asynchronously (does not block response)
    ctx.waitUntil(processInBackground(request, env));

    return response;
  }
};

// Strategy 2: Offload heavy work to a Queue
ctx.waitUntil(
  env.MY_QUEUE.send({
    type: 'process-image',
    url: imageUrl,
    userId: userId,
  })
);
// Queue consumer Worker handles the actual processing
Share this tool: X / Twitter LinkedIn
✓ 60,000+ developers use DevPlaybook ★★★★★ 4.8 / 5 on Gumroad ✓ MIT licensed · Instant download ✓ No login required

Related Products

on Gumroad

You Might Also Need

More Free Tools

Enjoying this tool? Get more like it.

Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.

DevPlaybook Pro 7 days free

Unlock AI-Powered Dev Tools

  • ⚡ AI Code Review, Doc Generator & SQL Builder
  • ⚡ All premium templates & early access
  • ⚡ Member discounts on Gumroad products
Start Free Trial →

$9/mo after trial · Cancel anytime

Want the full toolkit?

Get DevPlaybook Pro

Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.

$79
$241 separately Save $162 (67% off)
Get DevPlaybook Pro — $79 →

MIT licensed · Instant download · No subscription

See what's included → Browse all deals →

Frequently Asked Questions

What is the CPU time limit for Cloudflare Workers?▼

On the Free plan, Workers have a 10ms CPU time limit per request. On the Paid plan ($5/month), the limit increases to 50ms CPU time. Note that CPU time is wall-clock time minus I/O wait time — if your Worker spends most of its time waiting for fetch() calls, that does not count against your CPU budget. Workers that exceed their CPU limit receive an error response.

What is the difference between Workers, Pages Functions, and Durable Objects?▼

Cloudflare Workers are standalone serverless functions deployed to the edge. Pages Functions are Workers deployed alongside a Cloudflare Pages site (same runtime, co-located). Durable Objects provide stateful Workers with consistent identity — each Durable Object instance has a single-threaded execution guarantee and persistent storage, making them suitable for real-time collaboration, game servers, and coordination tasks.

What are the storage limits for Workers KV?▼

Workers KV has a 25MB value size limit per key and 512-byte key size limit. KV is eventually consistent (reads may lag writes by seconds across PoPs). For the Free plan, you get 100,000 KV reads/day and 1,000 writes/day. The Paid plan includes 10M reads/month and 1M writes/month. KV is optimized for read-heavy workloads — for write-heavy use cases, consider Workers D1 or R2.

What is the request size limit for Cloudflare Workers?▼

Workers can receive request bodies up to 100MB in size. Response bodies have no explicit size limit but are streamed. For the subrequest limit (fetch() calls from within a Worker), you can make up to 50 subrequests per Worker invocation on the Free plan and 1,000 on the Paid plan. Recursive Workers (Workers calling Workers) count toward this limit.

How does Workers Paid plan pricing work?▼

The Workers Paid plan costs $5/month and includes 10 million requests/month. Beyond that, additional requests cost $0.30 per million. CPU time beyond 30ms per request is charged at $0.02 per million CPU-ms. Compared to AWS Lambda, Workers pricing is often lower for high-throughput, short-duration workloads because there is no per-GB-second memory charge.

Can Cloudflare Workers connect to external databases?▼

Workers cannot make TCP connections (no traditional database drivers). For databases, use HTTP-compatible options: Cloudflare D1 (SQLite via Workers binding), Neon PostgreSQL (HTTP driver), PlanetScale (HTTP driver), Upstash Redis (HTTP), or Turso (libSQL over HTTP). For workers that must access a private database, use Cloudflare Tunnel with a Hyperdrive binding to proxy TCP connections.