Skip to content
·11 min read

Cloudflare R2 vs AWS S3 for Object Storage Compared

Zero egress fees vs ecosystem maturity and when each object storage service makes more sense

Share

Cloudflare R2 vs AWS S3 is the object storage decision that keeps showing up in architecture reviews. With 92% of developers using AI tools daily to ship faster, the storage layer you pick determines whether your bandwidth bill stays predictable or spirals with every successful product launch. Two services dominate this space, and they approach the economics of storing and serving files from fundamentally different directions.

Think of it this way. AWS S3 is a massive warehouse with incredible inventory management, security cameras on every aisle, and automated sorting systems. But every time a truck leaves the loading dock to deliver something, you pay a delivery fee. Cloudflare R2 is a warehouse that eliminated delivery fees entirely. The trucks roll out for free. The warehouse itself is simpler, with fewer bells and whistles, but for workloads where delivery costs dominate your bill, that difference changes everything.

Quick Verdict

Cloudflare R2AWS S3
Best forHigh-egress workloads, CDN-heavy appsComplex data pipelines, enterprise compliance
Storage cost$0.015/GB per month$0.023/GB per month (Standard)
Egress cost$0$0.09/GB (first 10TB)
S3-compatible APIYesNative
Lifecycle rulesBasic (expiration only)Advanced (transitions, intelligent tiering)

The right choice depends on whether your workload is egress-heavy or feature-heavy. For many applications, the answer is more obvious than you might expect.

Key Takeaway

Cloudflare R2 uses an S3-compatible API, which means most existing S3 code works with minimal changes. You swap the endpoint URL and credentials, and your existing SDK calls, CLI commands, and infrastructure-as-code templates carry over. The migration path is not a rewrite. It is a configuration change. This compatibility is what makes R2 a genuine alternative rather than a locked-in proprietary service.

Where R2 Wins on Economics

The headline feature of Cloudflare R2 is zero egress fees. Every byte that leaves your bucket costs nothing. For context, AWS S3 charges $0.09 per GB for the first 10TB of egress per month, dropping to $0.085 for the next 40TB. On a media-heavy application serving 10TB of images and video per month, that is $900/month in S3 egress alone. On R2, that same workload costs $0 in bandwidth.

This is not a marginal difference. It is the entire delivery fleet running for free.

Storage costs also favor R2 at $0.015/GB versus S3's $0.023/GB for Standard tier. On 1TB of stored data, that saves roughly $8/month. Not dramatic on its own, but combined with zero egress, the total cost picture shifts significantly for read-heavy workloads.

R2 also includes free operations for Class A (writes) up to 1 million per month and Class B (reads) up to 10 million per month. S3 charges for every operation from the first request. For applications with high request volumes (thumbnail serving, API responses, static assets), those free tiers eliminate another line item from your bill.

The warehouse analogy holds. R2's warehouse charges less rent per square foot, and every delivery truck leaves the dock without a toll. If your application is mostly about serving files to users, the math is straightforward.

EXPLAINER DIAGRAM: A side-by-side cost comparison on white background. Left side labeled CLOUDFLARE R2 shows three cost boxes stacked vertically: STORAGE at $0.015 per GB per month, EGRESS at $0 with a green highlighted FREE badge, and OPERATIONS showing 1M writes and 10M reads free per month. Right side labeled AWS S3 shows three matching boxes: STORAGE at $0.023 per GB per month, EGRESS at $0.09 per GB with a red highlighted ADDS UP FAST badge, and OPERATIONS showing charges from first request. Between the two sides, a large arrow points from S3 to R2 with text reading SAME API DIFFERENT BILL. Bottom note reads Example 10TB egress per month costs $0 on R2 vs $900 on S3.
The egress pricing difference is where R2 delivers the most dramatic savings for read-heavy workloads.

Where S3 Wins on Features

AWS S3 has been around since 2006. Twenty years of feature development gives it capabilities that R2 simply does not match yet.

Storage classes and intelligent tiering. S3 offers Standard, Infrequent Access, One Zone-IA, Glacier Instant Retrieval, Glacier Flexible Retrieval, Glacier Deep Archive, and Intelligent Tiering that automatically moves objects between classes based on access patterns. R2 offers one storage class. If you have cold data that you rarely access but need to retain for compliance, S3's tiered pricing can actually undercut R2 on storage costs alone. Glacier Deep Archive runs $0.00099/GB per month, roughly 15x cheaper than R2's single tier.

Lifecycle policies. S3 lifecycle rules can transition objects between storage classes, expire old versions, clean up incomplete multipart uploads, and manage object lock retention. R2 supports basic expiration rules but lacks the granular transition policies that make S3's tiered storage useful.

IAM and access control. AWS Identity and Access Management is the most sophisticated cloud permissions system available. You can grant bucket access based on user identity, role assumption, IP range, time of day, MFA status, VPC endpoint, and dozens of other conditions. R2 uses API tokens with basic read/write permissions per bucket. For organizations with strict compliance requirements and auditors who want to see fine-grained access logs, S3's IAM integration is a hard requirement.

Event notifications and integrations. S3 triggers Lambda functions, SQS queues, SNS topics, and EventBridge rules when objects are created, deleted, or modified. R2 supports event notifications through Cloudflare Workers, but the ecosystem of downstream integrations is smaller.

Versioning and replication. S3 offers object versioning, cross-region replication, same-region replication, and batch operations for managing billions of objects. R2 does not currently support versioning or cross-region replication.

Back to the warehouse analogy. S3's warehouse has a sophisticated inventory management system, climate-controlled zones for different types of goods, automated forklifts, and security protocols that satisfy government auditors. R2's warehouse is clean and efficient, but it stores everything in one zone and the inventory system covers the basics.

S3-Compatible API in Practice

R2 implements the S3 API, which means the AWS SDK works with R2 by changing the endpoint configuration. Here is what that looks like in practice.

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'

const r2 = new S3Client({
  region: 'auto',
  endpoint: 'https://<ACCOUNT_ID>.r2.cloudflarestorage.com',
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID,
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
  },
})

await r2.send(new PutObjectCommand({
  Bucket: 'my-bucket',
  Key: 'uploads/photo.webp',
  Body: fileBuffer,
  ContentType: 'image/webp',
}))

The core operations work as expected. PutObject, GetObject, DeleteObject, ListObjectsV2, HeadObject, multipart uploads, and presigned URLs all function correctly. Most applications that use S3 for file storage and serving can migrate by updating the client configuration.

However, some advanced S3 features are not supported. Object Lock, S3 Select (querying within objects), bucket policies with complex conditions, and some metadata operations behave differently or are absent. If your application relies on these, you will need to test thoroughly before migrating.

Common Mistake

Assuming that S3 API compatibility means full feature parity. R2 covers the core storage and retrieval operations that most applications need, but it does not support every S3 feature. Before migrating a production workload, audit which S3 API calls your application actually makes. The common operations (put, get, delete, list, presigned URLs, multipart upload) all work. The edge cases around versioning, object lock, and complex bucket policies do not. Test your specific integration rather than assuming everything transfers cleanly.

Performance Differences

S3 operates from specific AWS regions. Your bucket lives in us-east-1 or eu-west-1, and latency depends on how far your users are from that region. You can add CloudFront as a CDN layer for global performance, but that adds configuration complexity and its own egress pricing.

R2 stores data on Cloudflare's global network. While primary storage lives in a specific location, R2 automatically caches frequently accessed objects closer to where they are requested. Combined with Cloudflare's CDN (which is essentially free for R2 objects served through a custom domain), the performance for globally distributed read-heavy workloads is competitive without additional CDN configuration.

For write-heavy workloads or applications that need guaranteed single-region consistency, S3's explicit region model gives you more control over data placement and latency characteristics.

EXPLAINER DIAGRAM: A feature comparison matrix on white background with two columns labeled R2 WINS and S3 WINS. Under R2 WINS, four items each with a green checkmark: Zero egress bandwidth costs, Lower base storage price at $0.015 vs $0.023 per GB, Built-in global CDN caching, and Free tier for read and write operations. Under S3 WINS, four items each with a blue checkmark: Storage class tiering including Glacier, Advanced IAM and access policies, Object versioning and replication, and Deep ecosystem integrations with Lambda and SQS and EventBridge. A horizontal divider separates the matrix from a summary row reading BOTH SHARE S3-compatible API and core put get delete list operations.
The feature gap narrows every year, but S3's ecosystem integrations and storage tiering remain significant advantages for complex architectures.

When to Pick Each Service

R2 is the better choice when your workload is dominated by serving files to users. Image hosting, video delivery, static site assets, file downloads, API responses with binary payloads, and any scenario where egress costs would be a significant portion of your S3 bill. If you are building a media-heavy application, a CDN-backed website, or a SaaS product that serves user-uploaded files, R2's zero egress pricing eliminates the anxiety of going viral. Your storage bill stays flat regardless of traffic spikes.

S3 is the better choice when you need the broader AWS ecosystem. Data pipelines that trigger Lambda functions on upload, compliance workloads requiring object lock and Glacier archival, multi-region replication for disaster recovery, and enterprise environments where IAM policies are reviewed by security teams. If your storage is part of a larger AWS architecture with tight integrations between services, the operational overhead of splitting storage away from the rest of your infrastructure usually is not worth the egress savings.

The hybrid approach works too. Use S3 for your data pipeline and archival storage where the ecosystem integrations matter. Use R2 for your public-facing asset delivery where egress costs dominate. Many teams run both, routing internal data through S3 and user-facing content through R2. The S3-compatible API makes this straightforward since your application code uses the same SDK for both, just pointed at different endpoints.

Building Something That Serves Files?

Learn how to architect your storage layer for production workloads without surprise bandwidth bills.

See the full guide

What This Means For You

The Cloudflare R2 vs AWS S3 decision comes down to a simple question. Is your primary cost driver storage or delivery?

If your application stores 100GB but serves 10TB per month (think image-heavy apps, media platforms, or CDN-backed sites), R2 saves you hundreds or thousands of dollars monthly with zero egress fees. The warehouse ships for free, and for delivery-heavy workloads, that is the only number that matters.

If your application stores 10TB but serves modestly, relying on Lambda triggers, lifecycle transitions to Glacier, cross-region replication, and fine-grained IAM policies, S3's feature depth justifies the higher per-GB cost. The warehouse management system matters more than the delivery fees when your architecture depends on it.

For most developers building modern web applications, SaaS products, or content platforms, R2 handles the common case at a lower price point. The S3-compatible API means you are not locked in. You can start with R2 and move specific workloads to S3 if you hit a feature gap, or start with S3 and migrate your egress-heavy buckets to R2 when the bandwidth bill gets uncomfortable. The API compatibility gives you that flexibility without rewriting application code.

Planning Your Cloud Architecture?

Get practical guidance on choosing the right tools for each layer of your stack.

Explore the toolkit

Pick based on your actual cost structure and feature requirements, not brand familiarity. The best storage service is the one where your bill reflects what you store, not what you serve.

PJ
Pranay Joshi

20+ years building products at scale. VP of Product & Engineering, startup founder, and AI coach. Helping dreamers turn ideas into reality with vibe coding.

Written forDevelopers

The Tuesday Shipping Report

Every Tuesday, one focused email:

  • - The tool or technique that's actually working right now
  • - A real problem from the community (and how to solve it)
  • - What changed this week in the vibe coding landscape

Read by 1,000+ founders, developers, and creators building with AI. Free forever. No spam.