On this page
You’re storing files somewhere, images, downloads, video, and the two names that come up are Amazon S3, the incumbent everyone knows, and Cloudflare R2, the newer challenger. The headline everyone repeats is “R2 has no egress fees.” True, but what does that actually mean for your bill, and does it matter for a website or a CMS? Let’s get concrete.
The 30-second version
Both R2 and S3 are object storage, buckets of files you access over HTTP by key, the standard way to store media and assets for a website. They’re broadly similar in what they do. The big, real difference is pricing shape:
- S3 charges you to store data, to make requests, and to send data out, that last one is egress (a.k.a. “data transfer out”).
- R2 charges you to store data and make requests, but does not charge egress fees at all.
That single difference changes the economics for anything that serves a lot of files to the public, which is exactly what a website’s media is.
What “egress fees” actually means
Egress is the cost of data leaving the cloud provider’s network. Every time someone loads an image, downloads a PDF, or streams a video from your S3 bucket, those bytes travel out to the visitor, and S3 meters that outbound transfer and bills you per gigabyte.
Here’s the thing that catches people: you pay egress every single time the file is served. A popular image isn’t a one-time cost; it’s a cost per view. Storing 50 GB of media is cheap. Serving that media to a million visitors a month is where an S3 bill quietly balloons, and it scales with your success, which is the worst time for a surprise cost.
R2 removes that line item entirely. You pay to store the bytes and for the operations, but serving them out to the world is free, no matter how popular a file gets.
R2 is S3-compatible, that’s a big deal
R2 didn’t invent a new API. It implements the S3 API, so the huge ecosystem built around S3, the AWS SDKs, the aws CLI, tools, libraries, examples, mostly works against R2 by changing an endpoint and credentials. That dramatically lowers the switching cost:
# R2 exposes an S3-compatible endpoint; point existing S3 tooling at it.
aws s3 ls --endpoint-url https://<account-id>.r2.cloudflarestorage.com
# Or use Cloudflare's own wrangler CLI:
npx wrangler r2 bucket create my-site-media
npx wrangler r2 object put my-site-media/img/cover.jpg --file=./cover.jpg
So you’re not betting on a proprietary lock-in; you’re using a well-understood interface with better egress economics.
Where S3 still wins, be fair
R2 isn’t strictly better at everything, and a straight-shooting comparison has to say so:
- Ecosystem depth. S3 is ~20 years old and sits at the center of the AWS universe. If your whole stack is on AWS, keeping storage in S3 means data lives next to your compute, IAM, and everything else, no cross-cloud hops.
- Feature surface. S3 has an enormous, mature feature set: storage tiers (Glacier and friends for cold archival), fine-grained lifecycle rules, deep analytics, and integrations refined over two decades. R2 covers the common cases well and keeps adding features, but S3 is the more complete product today.
- Regional and compliance controls. AWS’s mature region and compliance tooling is hard to match if you have strict data-residency requirements.
If you live entirely inside AWS and rarely serve public traffic, S3’s in-network transfer and ecosystem may matter more than egress savings. Know your own workload.
Quick comparison
| Cloudflare R2 | AWS S3 | |
|---|---|---|
| Storage type | Object storage | Object storage |
| Egress fees | None | Per-GB, every time served |
| API | S3-compatible | S3 (the original) |
| Ecosystem | Growing, S3-compatible tooling | Vast, mature, 20 years |
| Storage tiers / archival | Fewer options | Extensive (Glacier, etc.) |
| Best when | Serving media publicly, cost-sensitive | Deep in AWS, in-network use |
Why this matters so much for a CMS
Here’s the punchline for anyone running a website. A CMS’s media, hero images, gallery photos, downloads, embedded video, is served publicly, over and over, to every visitor. That’s the exact workload egress fees punish. The more your content succeeds, the more S3 charges you to serve the files that made it succeed.
This is precisely why EmDash, Cloudflare’s open-source CMS, stores its files in R2. Every image on an EmDash site is served with no egress fee, so your media bill doesn’t scale with your traffic. Combined with Workers running your code at the edge and D1 holding your structured content, R2 completes a serverless stack where the whole thing scales to zero when idle and doesn’t nickel-and-dime you when it’s busy. It’s part of why Cloudflare’s own blog, running on EmDash, could absorb a 28,000 RPS DDoS without a runaway bill.
When you migrate a site to EmDash, moving media to R2 is a standard step, you sync your existing images into a bucket and rewrite the URLs. The WordPress-to-EmDash guide and the deploy guide both walk through it, and it’s the same pattern whatever you’re coming from.
The honest bottom line
If you’re storing files that lots of people will download, which is any public website’s media, R2’s no-egress-fee model is a real, ongoing cost advantage, and its S3 compatibility means you’re not giving up the familiar tooling to get it. If your storage lives deep inside AWS and rarely leaves the network, S3’s maturity and in-ecosystem fit may still win. For a CMS specifically, though, egress-free wins the argument most of the time, which is exactly the bet EmDash makes.
We cover this because our readers ask about it. What we actually do at 2emdash is rebuild ageing websites on Cloudflare and hand the owner a simple panel to run them from. We’re an independent service, not affiliated with Cloudflare or the EmDash project.