· cloudflare / aws / cost

Cloudflare vs AWS: the complete cost breakdown at scale

Cloudflare wins most mid-scale workloads; AWS wins large databases. Real cost breakdown: Workers vs Lambda, R2 vs S3, D1 vs RDS with exact figures.

By Ethan

2,155 words · 11 min read

For most new projects, the Cloudflare stack — Workers, R2, D1 — costs less than the AWS equivalent. Sometimes significantly less. The gap is structural: R2 charges $0 for egress where S3 charges $0.09/GB, and Workers bills CPU time only where Lambda bills wall-clock time including idle network waits. Past medium scale — databases above 10 GB, memory demands above 128 MB per function, jobs longer than five minutes — AWS wins.

Who this is for

Developers picking infrastructure for a new project. Also worth reading if you’re on AWS and want a concrete answer to whether the migration math works in your favor.


Why the bills look so different

Two decisions explain most of the cloudflare vs aws cost gap.

Egress. AWS charges $0.09/GB leaving S3 to the internet. Cloudflare R2 charges $0. For an application pushing 10 TB/month outbound, that’s $900/month you don’t owe on R2. The architectural reason this costs AWS money is real — bandwidth is expensive at S3 scale — but the practical outcome for your invoice is what matters.

Billing unit for compute. Lambda charges for every millisecond your function is alive, including the time it spends waiting for a database response or an external API. A function that runs for 200ms total but only does 7ms of CPU work gets billed for the full 200ms. Workers bills CPU time only. That 193ms of network wait is free.

Cloudflare migrated Workers to CPU-time billing on March 1, 2024. It applies to every Workers deployment today, not a special tier.


Scenario 1: API backend

Setup: 100M requests/month, typical REST API — database read, JSON response. CPU time per request: 7ms. Wall-clock duration: ~200ms (the rest is I/O wait).

Cloudflare Workers (Workers Paid plan, $5/mo base):

Cost lineCalculationAmount
SubscriptionFlat$5.00
Requests90M over included × $0.30/M$27.00
CPU time670M ms over included × $0.02/M CPU-ms$13.40
Total$45.40/month

AWS Lambda (128 MB, 200ms duration, x86):

Cost lineCalculationAmount
Requests100M × $0.20/M$20.00
Duration100M × 0.125 GB × 0.200s × $0.0000166667$41.67
Total$61.67/month

Workers is 26% cheaper here. The gap is driven by Lambda billing those 193ms of idle I/O per invocation.

Now take an I/O-heavy variant: same 100M requests, but the function waits on an external LLM or slow service — 5ms CPU, 1,000ms wall-clock duration.

Cloudflare Workers (same plan):

  • CPU: 500M ms − 30M included = 470M × $0.02/M = $9.40
  • Requests: $27.00
  • Total: ~$41.40/month

AWS Lambda (128 MB, 1,000ms):

  • Duration: 100M × 0.125 GB × 1.0s × $0.0000166667 = $208.33
  • Requests: $20.00
  • Total: ~$228.33/month

Workers is 82% cheaper for I/O-heavy workloads. Lambda bills every millisecond your function waits; Workers does not. For AI inference endpoints, third-party API calls, or anything with significant network round-trips, this difference compounds quickly.

For a deeper comparison of the runtime and cold-start differences between Workers and Lambda, see Cloudflare Workers vs AWS Lambda.


Scenario 2: Object storage and egress

Setup: Media hosting site — 100 TB stored, 50 TB egress per month, 1B GET requests.

Cloudflare R2:

Cost lineCalculationAmount
Storage100,000 GB × $0.015$1,500
Class B reads (GET)1B × $0.36/M$360
Egress$0$0
Total$1,860/month

AWS S3 (Standard, us-east-1, direct internet egress):

Cost lineCalculationAmount
Storage100,000 GB × $0.023$2,300
GET requests1B × $0.40/M$400
Egress (first 10 TB)10,240 GB × $0.09$921.60
Egress (next 40 TB)40,960 GB × $0.085$3,481.60
Total~$7,103/month

R2 is 74% cheaper. The entire saving is egress elimination — $4,403 of the $5,243 difference is bandwidth charges.

At small scale the gap is proportionally smaller but still present:

10 GB stored, 100 GB egress, 100M GET requests:

Cloudflare R2AWS S3
Storage$0 (free tier)$0.23
GET requests$36.00$40.00
Egress$0$9.00
Total$36/month$49.23/month

R2’s free tier covers 10 GB storage and 10M Class B reads per month. Small apps may pay nothing.

R2 limitations vs S3 worth knowing:

  • No Glacier-class archive tiers (Infrequent Access exists; deep archive does not)
  • No server-side encryption with customer keys (SSE-C) as of May 2026
  • S3 Event Notifications integrate tightly with Lambda; R2’s event system is simpler
  • S3 has 13+ storage classes; R2 has two

For compliance-heavy or archive-heavy workloads, the S3 feature set still has a real advantage beyond price.


Scenario 3: Database

Cloudflare D1 is SQLite over HTTP with scale-to-zero pricing billed by rows read and written — not by instance hours. That model is excellent for light workloads and punishing for heavy ones.

Light backend — 1B reads/month, 10M writes/month, 2 GB data:

Cloudflare D1 (on Workers Paid):

  • Rows read: 1B vs 25B included → $0
  • Rows written: 10M vs 50M included → $0
  • Storage: 2 GB vs 5 GB included → $0
  • Total: $0 additional (inside the $5/mo Workers Paid allowance)

AWS RDS MySQL (db.t3.micro, single-AZ):

  • Instance: ~$12.41/month
  • Storage (20 GB minimum, gp2): $2.30
  • Total: ~$14.71/month

AWS Aurora Serverless v2 (MySQL-compatible):

  • Minimum: 0.5 ACU × $0.12/ACU-hr × 730 hrs = $43.80/month, even when idle
  • Total: ~$47+/month minimum

D1 wins at light scale. Aurora Serverless bills a minimum whether or not your app gets traffic, which makes it worse than RDS for low-traffic workloads.

Medium backend — 50B reads/month, 500M writes/month, 25 GB data:

Cloudflare D1:

  • Rows read: (50B − 25B) × $0.001/M = $25
  • Rows written: (500M − 50M) × $1.00/M = $450
  • Storage: (25 GB − 5 GB) × $0.75/GB = $15
  • Total: $490/month (plus $5 base)

AWS RDS MySQL (db.t3.medium, Multi-AZ):

  • Instance: ~$49.64 × 2 = $99.28
  • Storage (50 GB gp2): $5.75
  • Total: ~$105/month

RDS wins by 4.5×. D1’s row-write cost ($1/M rows) accumulates fast once writes scale up. A write-heavy workload is exactly where the per-row model breaks down.

D1 hard limits that matter regardless of price:

  • Max database size: 10 GB (not a soft limit — the DB won’t write past it)
  • Single-threaded execution (one query at a time)
  • SQLite dialect only — no stored procedures, no triggers, no full-text search
  • Max row or BLOB: 2 MB
  • Query timeout: 30 seconds

Use D1 for feature flags, user preferences, small catalog tables, and light-read workloads. Don’t use it for anything that will grow past 10 GB or that requires concurrent write throughput.

If you’re evaluating PostgreSQL-compatible serverless options as an alternative to both D1 and RDS, see Neon vs Supabase for a direct comparison of those platforms.


Summary tables

All prices from official vendor pages as of 2026-05-20.

Workers vs Lambda — 7ms CPU, 200ms wall-clock, 128 MB

Monthly requestsWorkersLambdaWorkers advantage
15M$8.00$9.25−13%
100M$45.40$61.67−26%
1B$231.40$481.67−52%

For I/O-heavy workloads (5ms CPU, 1,000ms duration), Lambda at 1B requests costs ~$2,083/month vs Workers at ~$215/month. The Workers advantage grows with I/O wait time.

R2 vs S3 — egress only, Standard class

Monthly egressCloudflare R2AWS S3R2 saving
1 TB$0~$92100%
10 TB$0~$894100%
100 TB$0~$8,704100%

R2 egress is $0 at every scale. Storage rate ($0.015/GB) is also lower than S3 Standard ($0.023/GB).

D1 vs RDS — cloudflare d1 vs rds summary

WorkloadD1RDS t3.microBetter
Light (1B reads, 10M writes, 2 GB)$0 extra$14.71/moD1
Medium (50B reads, 500M writes, 25 GB)$490/mo~$105/moRDS
Any workload over 10 GBNot viable$105–$400+RDS

When Cloudflare is the right call

Egress-heavy applications. Images, video thumbnails, file downloads, large API payloads. R2’s $0 egress is the biggest single lever in the comparison. If bandwidth is in your cost model, R2 wins at every volume.

I/O-heavy compute. REST APIs, webhook processors, authentication services — code that spends most of its runtime waiting on the network. Workers’ CPU-time billing means idle I/O doesn’t cost you.

Cold-start sensitivity. Cloudflare uses V8 isolates. Cold-start time is sub-millisecond. Lambda cold starts range from 100ms to over 1,000ms depending on runtime, memory, and whether the container is warm. For user-facing latency, the gap is material.

Small databases. D1’s scale-to-zero model and generous included allowances on the Workers Paid plan make it essentially free for low-volume workloads. No instance to keep running when traffic drops to zero.

Projects starting fresh without AWS dependencies. The integrated pricing model — Workers + R2 + D1 under one $5/month base — is simpler to reason about than assembling Lambda + S3 + RDS + CloudFront with separate billing for each.


When AWS is the right call

Databases that will grow past 10 GB. D1’s 10 GB ceiling is hard. Plan for it upfront — migrating from D1 to RDS after the fact is a real project. RDS MySQL/PostgreSQL scales to 64 TB.

Write-heavy database workloads. Once you’re doing hundreds of millions of writes per month, D1’s $1/M row-write rate exceeds what a flat RDS instance costs. The larger the write volume, the worse the D1 math.

Memory-intensive compute. Workers is fixed at 128 MB. Lambda scales to 10,240 MB. Machine learning inference, large in-memory operations, and heavy image processing need Lambda or Cloudflare Containers (available on Workers Paid plan, see Cloudflare Containers docs).

Long-running jobs. Lambda allows up to 15 minutes per invocation. Workers allow 5 minutes of CPU time. Batch jobs, data exports, and video encoding generally need Lambda or Containers.

Deep AWS ecosystem integration. Step Functions, EventBridge, SQS, SNS, RDS Proxy, Redshift — if these services are already load-bearing in your architecture, staying on AWS avoids significant integration work.

Data residency requirements. AWS has 30+ named regions with documented data-at-rest boundaries. Cloudflare PoPs are edge locations, not AWS-equivalent availability zones. Regulated workloads with specific data residency requirements are generally better served by a named cloud region.


Vietnam and SE Asia

Cloudflare operates PoPs in Hanoi, Ho Chi Minh City, and Da Nang. A Workers function invoked by a Vietnamese user runs at the nearest PoP — typically 5–15ms of network latency from the user’s device.

AWS has no region in Vietnam. The nearest is ap-southeast-1 in Singapore, which adds 30–60ms baseline for Vietnamese users before your code runs. Jakarta (ap-southeast-3) and Malaysia (ap-southeast-5) are closer to some users but not to Vietnam specifically.

For latency-sensitive workloads — real-time APIs, authentication flows, anything with p99 targets — this is a structural Cloudflare advantage that doesn’t show up in the pricing tables. It compounds the cost advantage with a performance one.

If you’re building for a Vietnamese audience without existing infrastructure, deploying on Cloudflare Pages with Workers handles both latency and cost in a single stack. See how to deploy an Astro site on Cloudflare Pages for a working setup guide.


Verdict

Use Cloudflare if you’re building a new API, storage-heavy app, or edge-served site without prior AWS dependencies — especially if your audience is in Vietnam or SE Asia. R2 + Workers on the $5/month Paid plan handles most small-to-medium workloads for less than the equivalent AWS stack.

Use AWS if your database will exceed 10 GB, you need more than 128 MB of memory per function, you’re running long batch jobs, or you’re already invested in AWS services that are hard to replicate on Cloudflare.

The migration path in either direction is not free, so pick based on where you expect to be in 18 months, not where you are today.

To start: Cloudflare Workers Paid is $5/month and includes enough compute and storage for most small projects. Cloudflare R2 starts pay-as-you-go with a free tier for the first 10 GB.


References