R2
vs
S3
Object Storage
egress • free tier • cost

Cloudflare R2 vs AWS S3: Cost, Egress Fees and Free Tier Compared

Compare Cloudflare R2 and AWS S3 on pricing, egress fees, free tiers, when R2 is cheaper, and how to migrate with an endpoint change.

11 min read16/06/2026

Pricing and free tier details in this article are based on publicly available information as of 16/06/2026. Verify against the official pricing pages before making a decision — both Cloudflare and AWS adjust pricing over time.

Quick verdict

  • R2 wins clearly for bandwidth-heavy workloads (serving files, media, downloads) — zero egress fees is the decisive advantage
  • S3 wins when you need deep integration in the AWS ecosystem: Lambda triggers, EventBridge, Athena, EMR, Step Functions...
  • R2's free tier is significantly better and never expires — S3 free tier only lasts 12 months for new accounts
  • Migrating from S3 to R2 is straightforward because R2 is S3-API compatible — just swap the endpoint

Quick comparison table

Cloudflare R2 AWS S3 (us-east-1)
Storage $0.015/GB/month $0.023/GB/month
Egress to Internet $0 — free $0.09/GB (first 10TB)
Class A (write, list) $4.50/million requests $0.005/1,000 requests
Class B (read, GET) $0.36/million requests $0.0004/1,000 requests
Free tier storage 10GB/month (never expires) 5GB/month (first 12 months)
Free tier requests 1M write + 10M read/month 2,000 PUT + 20,000 GET/month
S3-compatible API Yes — (native)
Built-in CDN Cloudflare global network Requires CloudFront (extra cost)

Egress fees — the reason R2 exists

AWS S3 charges $0.09/GB for every gigabyte transferred out to the Internet. For workloads that serve media, file downloads, or static assets, this is the biggest cost driver — not storage.

Real-world example:

An app with 100GB of data, serving 1TB of downloads per month:

R2 S3
Storage $1.50 $2.30
Egress (1TB) $0 $92.16
Requests (estimated) ~$1 ~$1
Monthly total ~$2.50 ~$95

About 38× difference — just because of egress. The gap widens as traffic increases.

Cloudflare R2 doesn't charge for egress because R2 sits on Cloudflare's own network — bandwidth is already accounted for in their infrastructure. This is exactly why R2 was built: to compete directly with AWS's egress pricing model.

Free tier in detail

Cloudflare R2 free tier

  • 10GB storage/month — no expiry, no credit card required to use the free tier
  • 1 million Class A operations/month (PUT, POST, COPY, LIST)
  • 10 million Class B operations/month (GET, HEAD)
  • Egress is always free, even beyond the free tier

Enough to run a small app or side project at zero cost.

AWS S3 free tier

  • 5GB storage/month — only applies for the first 12 months after account creation
  • 20,000 GET requests/month
  • 2,000 PUT requests/month
  • Egress is not included — downloads are billed even within the free tier

After 12 months, there's no more free tier. For long-running projects, S3 will have a cost even with small data volumes if there's any outbound bandwidth.

Features — S3 is still more complete

What R2 has

  • Core object storage (PUT, GET, DELETE, LIST)
  • Object versioning
  • Lifecycle rules (auto-delete objects after N days)
  • Presigned URLs
  • CORS configuration
  • Custom domains via Cloudflare
  • Event notifications via Cloudflare Queues
  • S3-compatible API (use the AWS SDK, just swap the endpoint)

What S3 has that R2 doesn't

  • Direct Lambda triggers on new objects — R2 requires routing through Queues + Workers
  • S3 Select — query data inside CSV/JSON/Parquet files without downloading them
  • S3 Inventory — scheduled reports listing all objects in a bucket
  • Storage Classes: Standard, Infrequent Access, Glacier — significant savings for cold data
  • Cross-region and cross-account replication
  • Native integration with dozens of AWS services: Athena, EMR, Redshift Spectrum, Glue, Step Functions, EventBridge...
  • Access Points — granular access control by VPC, prefix, or account
  • More regions (30+)

R2 is the right fit for storing and serving files. S3 is the right fit when storage is one link in a larger data pipeline.

Migrating from S3 to R2

R2's S3 API compatibility means migration usually only requires swapping the endpoint and credentials:

// Before: AWS S3
import { S3Client } from "@aws-sdk/client-s3";

const s3 = new S3Client({
  region: "us-east-1",
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  },
});

// After: Cloudflare R2 — only the endpoint and credentials change
const r2 = new S3Client({
  region: "auto",
  endpoint: `https://${process.env.CF_ACCOUNT_ID}.r2.cloudflarestorage.com`,
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID,
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
  },
});

All operations — PutObjectCommand, GetObjectCommand, DeleteObjectCommand — stay identical. No changes to business logic.

Migration notes:

  • Buckets must be recreated on R2 (no auto-sync)
  • Objects need to be copied manually or with rclone
  • If you're using S3 event triggers into Lambda, refactor to Cloudflare Queues + Workers
  • Presigned URL format changes endpoint but the generation logic is the same

Syncing data from S3 to R2 with rclone

# Configure R2 in rclone
rclone config create r2 s3 \
  provider Cloudflare \
  access_key_id YOUR_R2_KEY \
  secret_access_key YOUR_R2_SECRET \
  endpoint https://ACCOUNT_ID.r2.cloudflarestorage.com \
  acl private

# Copy entire bucket from S3 to R2
rclone copy s3:your-s3-bucket r2:your-r2-bucket --progress

R2 or S3 — which to choose

Choose R2 when:

  • App serves files, images, or video to users — save on egress
  • Side project or early startup keeping costs low
  • No need for deep AWS service integration
  • Want a free tier with no expiry

Choose S3 when:

  • System already runs on AWS and needs Lambda, Athena, EMR, or EventBridge integration
  • Need S3 Select to query data inside files directly
  • Require cross-region replication with specific SLA guarantees
  • Team is already familiar with AWS IAM and doesn't want another vendor

Use both when:

  • Store cold data or long-term backups on S3 Glacier (cheaper per GB)
  • Serve hot data, media, and assets via R2 (zero egress cost)