· cloudflare-workers / pricing / serverless
The real cost of running production on Cloudflare Workers
Workers is cheap for I/O-heavy APIs at high request volume. KV writes, D1 write bugs, and unhibernated Durable Objects are where bills go sideways.
By Ethan
2,984 words · 15 min read
Cloudflare Workers is genuinely cheap for certain workloads — and surprisingly expensive for others. The headline is $5/month for 10 million requests. The actual bill for a KV-write-heavy side project can hit $158/month. Two D1 runaway-write bugs hit one production developer with a $4,586 charge in a single billing cycle. This article shows the math, the traps, and the workloads where Workers wins or loses on cost.
Who this is for
Backend developers evaluating Cloudflare Workers for production — or already running on Workers and trying to understand why the bill is higher than expected. If you’re deciding between Workers, AWS Lambda, and Vercel for a new project, the comparison table will help you model costs before you commit. For a hands-on look at the runtime itself, the Cloudflare Workers review covers developer experience, limits, and the full feature set.
How Cloudflare Workers billing actually works
Workers switched to CPU-time billing in October 2023. You pay for the time your code is executing, not the total wall-clock duration of the request. If your Worker spends 100ms waiting for a D1 query and 5ms actually running JavaScript, you’re billed for 5ms of CPU time — not 105ms.
This is why I/O-heavy workloads are dramatically cheaper on Workers than on Lambda. Lambda billed on wall-clock from the start, so if your function spends 90% of its time waiting on DynamoDB, you pay for all of it. Workers does not. For a backend that’s mostly database reads and external API calls — which is most backends — this difference is real money.
Five meters make up a Workers bill:
| Meter | What it covers |
|---|---|
| Requests | Every HTTP request that hits a Worker |
| CPU time | Code execution time, in milliseconds |
| KV operations | Read and write operations to Workers KV |
| D1 operations | Read and write operations to D1 SQLite databases |
| Durable Objects | Requests to and duration of Durable Object instances |
R2 object storage has its own billing outside this table, covered in the gotchas section.
Free tier and Paid plan limits
The Workers free tier is limited to 100,000 requests/day and has no SLA. For production, you need the Paid plan at $5/month. That $5 includes:
| Meter | Included in Paid plan |
|---|---|
| Requests | 10M/month |
| CPU time | 30M CPU-milliseconds/month |
| KV reads | 10M/month |
| KV writes | 1M/month |
| D1 reads | 25B rows/month |
| D1 writes | 50M rows/month |
| D1 storage | 5 GB |
| Durable Objects requests | 1M/month |
| Durable Objects duration | 400,000 GB-sec/month |
| R2 storage | 10 GB/month |
| R2 Class B ops (reads) | 10M/month |
Beyond these limits, overage rates apply:
| Meter | Overage rate |
|---|---|
| Requests | $0.30/million |
| CPU time | $0.02/million CPU-ms |
| KV reads | $0.50/million |
| KV writes | $5.00/million |
| D1 reads | $0.001/million |
| D1 writes | $1.00/million |
| R2 storage | $0.015/GB-month |
| R2 Class A ops (writes, deletes, list) | $4.50/million |
| Durable Objects requests | $0.15/million |
| Durable Objects duration | $12.50/million GB-seconds |
| DO SQLite storage (since Jan 7, 2026) | $0.20/GB-month |
| Log events | $0.60/million |
The KV write rate — $5.00/million, 10× the read rate — is where most budget surprises live. Keep that number in mind as you read the scenarios below.
Three scenarios with line-item math
Scenario 1: solo side project, KV-heavy session storage
A developer tools side project receiving 5 million requests per day (150M/month), using KV to store session data. Each request triggers one KV read and one KV write.
| Line item | Volume | Rate | Cost |
|---|---|---|---|
| Base plan | — | — | $5.00 |
| Requests (150M – 10M included) | 140M | $0.30/M | $42.00 |
| KV reads (150M – 10M included) | 140M | $0.50/M | $70.00 |
| KV writes (150M – 1M included) | 149M | $5.00/M | $745.00 |
| CPU time (est. 3ms avg per request) | 450M CPU-ms – 30M included = 420M | $0.02/M | $8.40 |
| Total | ~$870/month |
That number looks alarming. It is. But notice that the KV write volume (150M/month from 5M req/day) is the specific driver. If you’re writing to KV once per session creation rather than once per request — and caching the session data in-memory for the lifetime of the Worker instance — the write volume drops 100× or more.
A more realistic version of the same project, with sessions created at login and read on each subsequent request:
| Line item | Volume | Rate | Cost |
|---|---|---|---|
| Base plan | — | — | $5.00 |
| Requests (150M – 10M included) | 140M | $0.30/M | $42.00 |
| KV reads (150M – 10M included) | 140M | $0.50/M | $70.00 |
| KV writes (est. 1M new sessions/month) | 0 overage | — | $0.00 |
| CPU time (est. 3ms avg) | 420M overage | $0.02/M | $8.40 |
| Total | ~$125/month |
Still not $5. At 150M requests/month you’re a legitimate mid-traffic app, and request overage alone is $42. But the difference between $870 and $125 is entirely write pattern — not request volume.
The Researcher’s original dossier cited ~$158/month for this scenario with partially optimized writes. That math checks out.
Scenario 2: SaaS backend, D1 + modest Durable Objects
An API backend for a subscription SaaS: 10M requests/month, each doing approximately 2 D1 reads and 0.1 D1 writes on average (reads dominate), plus 500K Durable Object requests for session management with low average hold time.
| Line item | Volume | Rate | Cost |
|---|---|---|---|
| Base plan | — | — | $5.00 |
| Requests | 10M included | — | $0.00 |
| D1 reads (20M rows – within 25B/month included) | 0 | — | $0.00 |
| D1 writes (1M rows – within 50M/month included) | 0 | — | $0.00 |
| DO requests (500K – within 1M/month included) | 0 | — | $0.00 |
| DO duration (~3,125 GB-sec – within 400K GB-sec/month included) | 0 | — | $0.00 |
| CPU time (est. 15ms avg) | 150M CPU-ms – 30M included = 120M | $0.02/M | $2.40 |
| Total | ~$7.40/month |
This is where Workers shines. A SaaS backend at 10M requests/month with a real database runs under $10/month if the write patterns are sane. The included limits do a lot of work at this scale — 25 billion D1 reads and 50 million D1 writes per month cover normal workloads entirely. The cost trap with D1 is not routine usage; it’s the lack of a hard billing cap when a bug causes runaway writes. The same workload on AWS Lambda plus API Gateway runs $38–45/month.
Scenario 3: compute-heavy image processing
Image resizing or transformation: 1M requests/month, each using ~80ms of actual CPU time.
| Line item | Volume | Rate | Cost |
|---|---|---|---|
| Base plan | — | — | $5.00 |
| Requests | 1M included | — | $0.00 |
| CPU time (80M – 30M included) | 50M CPU-ms | $0.02/M | $1.00 |
| Total | ~$6/month |
Workers is still cheap at low volume. Scale it to 10M requests/month at 80ms CPU each:
| Line item | Volume | Rate | Cost |
|---|---|---|---|
| Base plan | — | — | $5.00 |
| Requests (10M – 10M included) | 0 overage | — | $0.00 |
| CPU time (800M – 30M included) | 770M CPU-ms | $0.02/M | $15.40 |
| Total | ~$20/month |
Still cheaper than Lambda at this scale. But Workers caps memory at 128MB, which limits the complexity of in-memory image processing. For large file transforms, you’ll likely hit the 128MB ceiling before the billing becomes a concern.
Platform comparison at 10M requests/month
Fixed workload: 10M requests/month, 15ms average CPU time, read-dominant pattern.
| Platform | Monthly cost | Key difference |
|---|---|---|
| Cloudflare Workers | ~$5 | Base plan covers this workload entirely |
| AWS Lambda + API Gateway | ~$38 | Wall-clock billing + per-call API GW fee |
| Vercel Pro | $20/user/month + compute | Per-user pricing; compute beyond generous limits |
Lambda beats Workers when individual invocations average more than ~100ms CPU at high request volume. Above that threshold, Lambda’s ability to allocate up to 3,008MB of memory (and proportionally more CPU) changes the math. Workers is capped at 128MB and bills per CPU-ms — there’s no way to buy a faster instance.
For I/O-heavy workloads under the 128MB ceiling, Workers wins. For compute-heavy workloads at large memory requirements, Lambda is more flexible.
For a detailed head-to-head on latency, ecosystem, and cold starts, see the Cloudflare Workers vs AWS Lambda comparison.
Five hidden cost traps
1. D1 has no hard billing cap — the $4,586 disaster
In January 2026, a developer faced a Cloudflare bill of $4,586.64 from two separate D1 runaway incidents. In the first (Jan 11–14), a heritage-records worker missing deduplication wrote 3.45 billion rows over four days. In the second (Jan 1–4), a GitHub data harvester missing conflict handling inserted 910 million rows — a combined ~4.83 billion rows with no platform protection. D1 has no hard billing cap — no circuit breaker in the platform itself.
Cloudflare eventually waived the full amount, but it took 18 days. The full postmortem is at littlebearapps.com/blog/d1-billing-disaster-circuit-breakers/.
The failure mode here isn’t unique to D1 — any metered service can produce a runaway bill from a loop bug. D1’s low per-read cost ($0.001/M) makes it feel cheap; the write cost ($1.00/M, 1,000× higher than reads) is what actually kills you.
Three things to do before you ship any cron job or scheduled Worker against D1:
// Rate limit D1 writes via a KV counter
const key = `d1-write-counter:${new Date().toISOString().slice(0, 10)}`; // YYYY-MM-DD
const count = parseInt(await env.RATE_LIMIT.get(key) ?? '0', 10);
const DAILY_WRITE_LIMIT = 1_000_000; // tune to your expected max
if (count >= DAILY_WRITE_LIMIT) {
throw new Error(`D1 daily write limit reached: ${count}`);
}
await env.RATE_LIMIT.put(key, String(count + 1), { expirationTtl: 86400 });
// safe to proceed with D1 write
Also: set a Cloudflare billing alert at a dollar threshold you’d actually notice — before the code ships. The platform has this; most people don’t configure it.
For a deeper look at D1’s feature set, query limits, and SQLite compatibility, see the Cloudflare D1 review.
2. KV write asymmetry: 10× more than reads
KV reads cost $0.50/million. KV writes cost $5.00/million. The asymmetry exists because KV writes are globally replicated across Cloudflare’s network — the write cost reflects real infrastructure.
Patterns that hit this without warning:
- Writing session state on every authenticated request (auth token refresh, user presence updates)
- Using KV as a simple counter or analytics accumulator
- Storing per-request metadata for debugging
The pattern to replace most write-heavy KV use cases: write to KV only on explicit state change (login, logout, preference update). Cache in memory within the Worker instance for the duration of its lifecycle. Workers Analytics Engine is the right tool for event/metrics data — different billing model, built for append-heavy workloads.
3. Durable Objects without Hibernation API: idle WebSocket charges
Durable Objects bill on wall-clock duration: $12.50 per million GB-seconds. A Durable Object stays “alive” — and billing — as long as any WebSocket connection keeps it active.
Consider 1,000 persistent WebSocket connections, each holding a DO instance open for 24 hours:
1,000 DOs × 86,400 seconds × (128MB / 1,024) GB
= 1,000 × 86,400 × 0.125
= 10,800,000 GB-seconds/day
× 30 days = 324,000,000 GB-seconds/month
÷ 1,000,000 × $12.50 = $4,050/month
The Hibernation API suspends a DO when all its WebSocket connections go idle, resuming only on an incoming message. With hibernation, the billing flips from wall-clock to event-driven — you pay only for the brief CPU burst that handles each message, not for sitting idle between them.
At 1,000 connections with typical 1 message/second traffic:
1,000 DOs × 1,000 messages/day × 5ms CPU/message
= 5,000,000 CPU-ms/day = 150,000,000 CPU-ms/month
= 150M CPU-ms – 30M included = 120M overage
120M × $0.02/M CPU-ms = $2.40/month
That’s the difference between $4,050 and $2.40. The Hibernation API is not optional for production WebSocket servers. Liveblocks handles 500 million WebSocket messages/day on Workers using exactly this pattern.
4. Logging amplification: $0.60/million log events
Workers logging (Logpush, Console API) costs $0.60 per million log events. At verbose logging — 100 events per request, 10M requests/month — that’s 1 billion log events = $600/month in logging alone.
This is easy to overlook during development, where you never hit volume. Verbose request/response logging that costs nothing at 10,000 requests/day costs $600/month at 10M requests/month.
The standard fix: structured logging with sampling. In production, log errors and slow requests unconditionally; sample everything else at 1%. A 1% sample on info-level logs at 10M requests/month = 100K sampled events/month, well inside the included limit.
5. R2 Class A operations: zero egress ≠ zero cost
R2’s headline differentiator is zero egress fees — no charges for data leaving Cloudflare to your users. This is real and meaningful. S3 egress at scale is a significant bill; R2 eliminates it entirely.
But R2 still charges for Class A operations: writes, deletes, and list operations at $4.50/million. Serving a read-heavy CDN — a static asset store, an image library — is effectively free beyond storage. But write-heavy use cases pay for every object ingested.
10M object uploads/month = $45 in Class A ops. That’s actually cheaper than S3 PUT requests at $0.005/1000 ($50/M), but the “zero egress” framing can create a mental model where R2 is universally free. It’s free to serve; it’s not free to write.
For log archiving, event capture, or any pattern that uploads frequently, factor in Class A ops before assuming R2 is cost-free.
Real production at scale
Baselime: 83% cost reduction from AWS to Cloudflare
Baselime is an observability SaaS that moved its full infrastructure from AWS to Cloudflare in 2023. Total daily cloud cost dropped from $1,940 to $325 — an 83% reduction. Their workload is I/O-heavy: ingesting log lines, tracing spans, querying across customer event datasets. Exactly the workload where Workers’ CPU-time billing helps most. They were paying Lambda for wall-clock time on a workload that was 80%+ waiting on I/O.
Source: blog.cloudflare.com/80-percent-lower-cloud-cost-how-baselime-moved-from-aws-to-cloudflare/
Liveblocks: 500M WebSocket messages/day
Liveblocks runs collaborative editing infrastructure — multiplayer cursors, shared state, presence — on Workers with Durable Objects. At 500 million WebSocket messages/day, Durable Objects with the Hibernation API is the architecture. Without hibernation, the wall-clock DO duration cost would be unworkable at that message volume. This is the largest published Workers production deployment I’m aware of, and it’s built on the exact pattern (DO + hibernation) that the billing section above shows is essential.
Source: cloudflare.com/case-studies/liveblocks/
Verdict
Workers is the right call when:
- Your backend is I/O-bound — database queries, external API calls, anything waiting on the network. CPU-time billing makes these workloads dramatically cheaper than Lambda.
- You’re replacing Lambda + API Gateway for an API that handles high request volume at low CPU per request. At 10M requests/month with 15ms average CPU, Workers costs ~$5 vs Lambda’s ~$38. That gap is real.
- You need object storage without egress fees. R2 is legitimately better than S3 for read-heavy CDN patterns, and the absence of egress charges compounds over time.
- You’re building a simple CRUD API at modest scale. The included limits are generous enough that many low-to-mid traffic apps fit inside $5–15/month.
Watch out when:
- You write to KV frequently. Design for read-heavy KV access patterns from the start. If you’re writing on every request, rethink the architecture before you hit scale.
- You use D1 in any automated process — cron jobs, queue consumers, event-driven pipelines. The lack of a hard billing cap is not a theoretical risk. Add rate limiting, add billing alerts, and add a circuit breaker. Do this before the code ships.
- Your Durable Objects hold WebSocket connections. The Hibernation API is non-negotiable for production use. Implement it from day one, not after you see the wall-clock bill.
- Your Workers are compute-bound above ~50ms average CPU. Workers still beats Lambda in most cases, but the advantage narrows, and you’re capped at 128MB memory — which limits what you can do in-process.
- You turn on verbose logging in production. Structured, sampled logging is not a nice-to-have; at 10M requests/month it’s a $600/month decision.
Budget rule of thumb: $15–50/month for a modest production app using Workers, KV reads, and D1. $50–200/month for write-heavy apps or apps with Durable Objects at scale. $200+ only if you’re combining several of the write-heavy patterns simultaneously or running compute-intensive workloads at very high volume.
The $5/month headline is real for I/O-heavy APIs at up to 10M requests/month. The gap between headline and actual bill is driven almost entirely by KV writes, D1 write volume, and unhibernated Durable Object duration. Understand those three meters and you can predict your bill accurately before the surprises arrive.
References
- Cloudflare Workers pricing
- Durable Objects pricing
- Workers pricing: scale to zero
- 80% lower cloud cost: how Baselime moved from AWS to Cloudflare
- Cloudflare Workers vs AWS Lambda cost — Vantage
- D1 billing disaster & circuit breakers — LittleBear Apps
- Liveblocks & Cloudflare: 500M WebSocket messages/day — Cloudflare case study