Cloudflare
R2 vs S3: object storage without the egress bill
Cloudflare R2 charges nothing to read your data back out; S3 charges per gigabyte of egress. Here is when that difference dominates a bill, how compatible the two really are, and where S3 still makes more sense.
If you store files in the cloud — images, video, backups, user uploads, data exports — there is a good chance the largest line on your bill is not storage at all. It is egress: the per-gigabyte fee you pay every time data leaves the provider’s network. On Amazon S3 and most of its peers, storing a terabyte is cheap and serving it repeatedly is where the money goes. Cloudflare R2 was built around removing that second charge, and for the right workload the difference is not marginal.
This is a look at where R2’s model actually wins, how compatible it is with the S3 tooling you may already use, what a migration involves, and the cases where S3 is still the better call. We build on both, so this is not a pitch for one over the other — it is where each one fits.
The one difference that drives everything
S3 pricing has three moving parts: storage per gigabyte-month, a charge per operation (the requests that read and write objects), and egress per gigabyte transferred out to the internet. For many workloads the third is the one that quietly grows, because egress scales with how popular your data is, not how much of it you keep.
R2 keeps the storage charge and the per-operation charges, and sets egress to zero. You pay to store objects and to make requests against them; you do not pay to read the bytes back out. That is the whole thesis, and everything else follows from it.
List prices move, so treat any specific figure as something to check against current documentation before you plan around it. The shape, though, has been stable: R2’s storage rate sits in the same neighbourhood as S3 standard storage, and the egress line — which on S3 is often the biggest number — simply is not there on R2.
When egress dominates a bill
The question is not “is R2 cheaper” in the abstract. It is “what fraction of my bill is egress.” A few patterns make that fraction large:
- Public media served at scale. Images and video delivered to lots of visitors mean the same objects read thousands of times. Storage is fixed; egress climbs with traffic. This is the textbook case where R2 wins outright.
- Downloads and data exports. Software distribution, dataset hosting, report generation, anything where users pull large files repeatedly.
- Egress to other clouds or partners. Pulling data out of S3 into another provider, or shipping it to a partner’s systems, is billed egress every time.
- A busy content or asset backend. If you serve a catalogue, a media library, or user-generated content, your read-to-write ratio is heavily skewed toward reads — exactly the axis egress taxes.
If, on the other hand, you write a lot and read a little — cold archives, internal backups that are rarely restored, logs you keep for compliance and almost never touch — egress is a small slice and the storage rate matters more. Do the arithmetic on your own usage before you assume either way. The honest test is to pull your last few bills and see how much of the total is transfer.
There is a second, quieter benefit: R2 makes your costs predictable. Egress charges are the line that spikes when something goes viral or a client suddenly pulls their whole archive. Removing that line removes a class of surprise bills, which for a small business is worth something on its own.
How compatible is it, really
R2 exposes an S3-compatible API. In practice that means most tooling built for S3 — the AWS SDKs, common libraries, many backup and sync tools — can point at R2 by changing the endpoint and credentials rather than rewriting your code. For a large share of everyday operations (put, get, list, delete, multipart uploads) this works as you would expect.
The honest caveat is that “S3-compatible” is not “S3-identical.” S3 has accumulated a long tail of features and edge-case behaviours over many years, and not every one has an R2 equivalent, nor does every one behave byte-for-byte the same. If your application leans on a specific, less common S3 feature, verify it against R2’s current documentation rather than assuming parity. For mainstream object-storage use, the compatibility is close enough that migration is mostly configuration; for exotic use, check first.
R2 also has a native Workers binding, which is the more interesting story if you are already building on Cloudflare. From a Worker you can read and write objects directly without an HTTP round-trip out to a separate provider, which removes both latency and a whole category of cross-cloud egress. If your compute already lives at the edge, co-locating your storage there is the natural move — and it is where our Cloudflare work most often starts.
What a migration actually involves
Moving object storage is usually less dramatic than moving a database, but it deserves a plan.
- Inventory and measure. Know how much data you have, how it is accessed, and — critically — what your current egress bill looks like. That last number is what justifies the move or tells you not to bother.
- Copy the data. Tools exist to sync between S3-compatible stores; for large datasets the copy itself takes time and you will want to run it incrementally rather than in one shot.
- Handle the cutover. Decide whether you can tolerate a brief read-only window or need to run dual-write during the transition. For public assets, updating the URLs or putting Cloudflare in front is part of the plan.
- Watch the operations bill. Egress goes to zero, but per-operation charges do not. A workload with an enormous number of tiny requests should be modelled on operations, not just storage.
- Keep a rollback. Do not delete the source until you have verified reads against the new store under real traffic. The same discipline we apply to any infrastructure change: prove the new path works before you retire the old one.
The one-time cost worth naming is egress on the way out of S3 — copying your data out is itself billed transfer. For most datasets it is a modest, one-time charge against an ongoing saving, but for very large archives it is worth calculating before you commit.
Where S3 still fits
R2 removing egress does not make S3 the wrong choice everywhere.
- Deep AWS integration. If your systems already live in AWS and lean on S3 event notifications, Lambda triggers, Glacier archival tiers, or tight IAM integration, staying in the same platform can be worth more than the egress saving — especially since traffic between AWS services in the same region is not billed the same as internet egress.
- Cold archival at the lowest storage rate. For data you almost never read, the winning axis is the cheapest deep-archive storage tier, and AWS has mature options there. Zero egress does not help data you do not egress.
- A feature you specifically depend on. If your workload relies on an S3 behaviour without a clean R2 equivalent, the compatible-but-not-identical caveat above decides it.
The clean framing: if your bill is dominated by reads, R2’s zero-egress model is likely to save you real money and make the total predictable. If your bill is dominated by storage of rarely-read data, or by deep integration with the rest of AWS, S3 may still be the better home. Most businesses have both kinds of data, and the right answer is often to split them rather than to pick one store for everything.
If you are staring at an egress line that keeps growing and want a straight read on whether moving it to R2 pays off, that is the kind of question we answer in writing. Send us two paragraphs about what you store and how it is served, and we will reply within one business day.