pickuma.
Infrastructure

Tigris vs Cloudflare R2 vs Backblaze B2: Object Storage for Edge Apps in 2026

I moved three real workloads across Tigris, Cloudflare R2, and Backblaze B2 to figure out which S3-compatible store actually fits edge apps — egress, latency, and integration compared.

10 min read

I have a bad habit of treating object storage like a solved problem. You sign up for whatever your platform suggests, point the AWS SDK at a different endpoint, and never think about it again — until the bill arrives, or until a user in Singapore complains that uploads take four seconds. Over the last couple of months I moved three real workloads — a static asset bucket for a docs site, a user-upload pipeline for a small SaaS, and a nightly database backup job — across Cloudflare R2, Backblaze B2, and Tigris, and the differences turned out to be sharper than the marketing pages suggest.

The common ground is real: all three are S3-compatible, so in practice you change an endpoint URL, a region string, and a pair of credentials, and your existing code keeps working. That compatibility is the whole reason this comparison is even tractable. The interesting question is not “which API do I learn” — it is the same API — but “where does my data physically live, what does it cost to read it back, and how much of the surrounding plumbing do I have to build myself.” Those three questions sort the field cleanly.

The egress problem is the whole game

If you have ever been surprised by an AWS S3 bill, it was almost certainly egress. Storing a terabyte on S3 is cheap; serving that terabyte to the internet repeatedly is where the meter spins. AWS charges roughly nine cents per gigabyte of data transferred out to the internet, and for a content-heavy app that line item can dwarf the storage cost by an order of magnitude. Every alternative in this comparison exists, in part, as a reaction to that pricing.

Cloudflare R2’s headline pitch is the bluntest: zero egress fees. You pay for storage (in the rough neighborhood of $0.015 per GB-month as of mid-2026) and for operations — Class A writes and Class B reads, priced per million — but bandwidth out is free, full stop. For anything read-heavy, this changes the arithmetic entirely. A bucket that serves a viral asset, a popular dataset, or a media library does not punish you for being popular. There is a free tier as well, generous enough that small projects can run on R2 for nothing for a long time.

Backblaze B2 attacks the same problem from the storage side. Its at-rest price is the lowest of the three — around $0.006 per GB-month, give or take, which is roughly a third of S3 and noticeably under R2. B2 does charge for egress, but with two important escape hatches: a daily free-egress allowance scaled to how much you store, and, crucially, free egress when you serve through Cloudflare via the long-standing Bandwidth Alliance. Put a Cloudflare CDN in front of a B2 bucket and your read path can be effectively free while you pay the cheapest storage rate on the market.

Tigris does not try to win the price race. Its egress is competitively priced rather than free, and storage sits in the same general band as R2. What you are paying for instead is placement — your objects are replicated across regions automatically and served from close to the requester. That is a different value proposition, and it only makes sense once you stop thinking about the bill and start thinking about latency.

Latency and where your bytes actually sit

S3 compatibility tells you nothing about geography, and geography is where Tigris makes its case. R2 and B2 both store your data in a region (or, for R2, a location hint you can nudge), and Cloudflare’s network does the work of caching and serving close to users via its CDN. That CDN layer is excellent — for cacheable content, R2-behind-Cloudflare is genuinely fast almost everywhere. But the origin still lives somewhere specific, and a cache miss, or a write, or an uncacheable object, pays the round-trip to that origin.

Tigris is built differently. It is, at heart, a globally distributed store layered on FoundationDB, designed so that objects are replicated to multiple regions and the first byte comes from a nearby one without you orchestrating any of it. For workloads where reads are not cacheable — think per-user data, signed-URL access to private objects, or anything dynamic — that automatic regional replication is the headline feature. When I tested the user-upload pipeline, the difference between “single-region origin with a CDN in front” and “natively multi-region” showed up most clearly on first writes and on cold private reads from far away. On a static, cacheable docs bucket, honestly, I could barely tell the three apart once a CDN was in the path — the cache absorbs the difference.

The mental model I landed on: R2 and B2 are single-origin stores that you make fast with caching, and Tigris is a multi-origin store that is fast by construction. If your content is public and cacheable, caching wins and the cheaper option is fine. If your content is private, dynamic, or write-heavy and your users are spread across continents, native replication earns its keep.

Integration: how much plumbing comes in the box

This is where the three diverge most, and where your existing platform probably decides the answer for you.

R2 is a Cloudflare product, so its best trick is the tight binding to Workers. You can attach a bucket to a Worker as a native binding and read and write objects without an HTTP round-trip or even credentials in the usual sense — the storage is just there, in the same runtime, at the edge. If you are already building on Workers and Pages, R2 stops feeling like external storage and starts feeling like a local resource. It also exposes the standard S3 API for everything else, so tools like rclone, the AWS CLI, and S3 SDKs all work.

Tigris is woven into the Fly.io ecosystem the same way R2 is woven into Cloudflare’s. If you deploy apps on Fly, provisioning a Tigris bucket is a first-class command, credentials flow in as secrets, and the multi-region storage naturally complements Fly’s multi-region compute. It is available outside Fly too — it is a standalone S3-compatible service you can point anything at — but the smoothest experience, the one the product is clearly designed around, is the Fly developer running fly storage create and getting on with their day.

Backblaze B2 is the platform-agnostic one. It has no compute platform of its own to bind to, which is both its weakness and its honesty: it is pure storage. The integration story is “it speaks S3, and it pairs with Cloudflare for free egress.” For backups, archives, and any setup where you want storage decoupled from your application platform, that neutrality is a feature. B2 has been doing exactly this for years and the reliability reputation reflects it.

How they stack up side by side

ToolServiceEgressAt-rest priceGeo modelBest for
Cloudflare R2 Best for Edge apps already on CloudflareFree to internet~$0.015/GB-moSingle origin + Cloudflare CDNWorkers/Pages apps, read-heavy public assets
Backblaze B2 Best for Cheapest storage at scaleCharged, but free via Cloudflare + daily allowance~$0.006/GB-mo (cheapest)Single region + your chosen CDNBackups, archives, store-a-lot read-a-little
Tigris Best for Low global latency without DIY replicationCharged, competitiveComparable to R2Natively multi-region replicationDynamic/private global reads, Fly.io apps

A few honest caveats on that table. The prices are approximate and move; treat them as the shape of the market rather than a quote, and check the current pricing pages before you model a budget. “Free egress” on R2 is genuinely free for internet transfer, but operations (especially Class A writes) are not, so a write-heavy or many-small-objects workload can still run up a bill in a column you were not watching. And B2’s “free via Cloudflare” depends on the traffic actually traversing Cloudflare, as the warning above labors.

Who should pick which

Static assets and public media (docs sites, images, downloads): R2 is the path of least resistance. Free egress plus Cloudflare’s CDN means a popular asset costs you essentially storage-only, and if you are on Pages it is one binding away. If you are storing genuinely large libraries and watching every cent, B2 behind Cloudflare gets you the cheapest storage with the same free read path — at the cost of wiring up the CDN yourself.

User uploads in a multi-region app: This is Tigris’s sweet spot. Uploads are writes, profile reads are often private and uncacheable, and your users are everywhere. Native replication means the person in Sydney is not waiting on a us-east origin. If your users are concentrated in one region, the advantage shrinks and R2 is simpler.

Backups and archives: B2, almost reflexively. You are optimizing for the lowest at-rest price and you read the data rarely, so egress barely matters and storage cost dominates. Decoupling backups from your app platform is also good hygiene — you do not want your backup target to disappear with your compute vendor.

Edge apps on a specific platform: Let the platform decide. On Cloudflare, R2. On Fly.io, Tigris. The native binding or first-class CLI is worth more in daily ergonomics than a marginal price difference, and both expose the S3 API for the cases the native path does not cover.

If you take one thing away: figure out your read pattern first. Read-heavy and public points at R2. Read-rarely points at B2. Read-dynamic-and-global points at Tigris. The S3 API means you can prototype against all three in an afternoon and switch later if you are wrong — which is the real luxury here.

FAQ

FAQ

Are Tigris, R2, and B2 really drop-in S3 replacements?+
For the common path — PutObject, GetObject, listing, presigned URLs — yes, you change the endpoint, region, and credentials and your S3 SDK code works. The edges differ: multipart upload details, lifecycle rules, event notifications, and some conditional-request semantics are where 'compatible' gets fuzzy. Test your actual upload and lifecycle code, not just a basic put, before committing.
Is Cloudflare R2 egress actually free with no asterisk?+
Data transfer out to the internet is genuinely free on R2 — that is the core of its pricing model. You still pay for storage and for operations, where Class A (writes, lists) cost more than Class B (reads). So a write-heavy or many-tiny-objects workload can run up costs in the operations column even though bandwidth is free.
How does Backblaze B2 get free egress, and what's the catch?+
B2 offers a daily free-egress allowance scaled to your stored volume, plus free egress for traffic served through Cloudflare via the Bandwidth Alliance. The catch is that the free Cloudflare path only applies when traffic actually flows through Cloudflare's network — direct hits to the B2 endpoint past the daily allowance are billed normally. Confirm your read path, not just your architecture diagram.
What makes Tigris different if they all speak S3?+
Tigris is built as a globally distributed store (on FoundationDB) that replicates objects across regions automatically and serves the first byte from a nearby one. R2 and B2 keep an origin in one place and rely on a CDN to get close to users. For cacheable public content the difference is small; for private, dynamic, or write-heavy global workloads, Tigris's native multi-region placement is the real advantage.
I'm not on Cloudflare or Fly.io — does platform lock-in matter?+
All three expose the standard S3 API, so none of them locks you in at the data-access layer; tools like rclone and the AWS CLI work everywhere. The lock-in is in the ergonomics: R2's Worker bindings and Tigris's Fly CLI are conveniences, not requirements. If you are platform-agnostic, B2 is the most neutral choice, and R2 is still attractive purely for its free internet egress.

Related tools

Some links above are affiliate links. We may earn a commission if you sign up. See our disclosure for details.

Related reading

See all Infrastructure articles →

Get the best tools, weekly

One email every Friday. No spam, unsubscribe anytime.