Cloudflare R2 Pricing 2026: Free Tier Limits, Egress Costs & When to Upgrade

By Nayan Kyada · · 6 min read

Part of The Sanity + Next.js Guide

Cloudflare R2 keeps coming up as an asset storage option for Next.js and Sanity projects, mostly because of one selling point: zero egress fees. But the free tier has real limits, and the per-operation pricing model trips people up. This post breaks down exactly what R2 costs in 2026, where the free tier runs out, and whether it makes sense over S3 or Cloudinary for a content-heavy site.

What the R2 free tier actually includes

R2's free tier resets monthly and covers three distinct cost axes: storage, Class A operations (writes, lists, deletes), and Class B operations (reads/downloads). The headline numbers as of September 2026:

ResourceFree monthly allowance
Storage10 GB
Class A operations (PUT, POST, DELETE, LIST)1,000,000
Class B operations (GET, HEAD)10,000,000
Egress (data transfer out)Unlimited — $0.00

Egress being free is the actual differentiator. S3 charges around $0.09/GB out to the internet (after AWS's monthly free data-transfer allowance). On a content site serving 20 GB/month of images, that's about $1.80 per month from S3 before you touch operations — not catastrophic, but it compounds. Cloudinary's free tier gives you 25 monthly credits shared across storage, bandwidth, and transformations (1 credit ≈ 1 GB stored or 1 GB delivered), so a busy month can knock you into a paid plan without warning.

For a Sanity project where image binaries live in Sanity's CDN and R2 is handling build artifacts, uploaded PDFs, or video segments, the free tier is rarely the bottleneck. Where it gets uncomfortable is when you start routing all your media through R2 — or when you lean on Workers to transform images at the edge.

Paid tier pricing

Once you exceed the free allowances, costs are straightforward but easy to under-estimate if you're only looking at storage:

Billable itemPrice (2026)
Storage beyond 10 GB$0.015 / GB / month
Class A operations beyond 1M$4.50 per million
Class B operations beyond 10M$0.36 per million
Egress$0.00 (always)
R2 Super Slurper ingress from S3$0.00

Storage pricing is competitive — AWS S3 Standard costs $0.023/GB, so R2 is roughly 35% cheaper per gigabyte. But R2's Class A operation cost is higher: S3 PUT requests run $0.005 per thousand ($5 per million) versus R2's $4.50. Close enough that it won't swing a decision.

The number that catches teams out is Class A operations during CMS-driven publishing workflows. Every time a Sanity webhook fires and your Next.js route handler writes a revalidated JSON blob or a pre-generated OG image back to R2, that's a Class A op. On a busy editorial day with 500 publishes, each triggering a cache-busted PUT, you're at 500 operations — nothing near the limit. But if you're also listing bucket contents for a sitemap job or running bulk migrations, the counter rises faster.

R2 vs S3 vs Cloudinary: cost comparison for a content site

Assumptions (list prices at the time of writing — check each vendor's pricing page): 50 GB stored, 100 GB egress per month, 5 million Class A ops, 50 million Class B ops — roughly a mid-size marketing site with a lot of image variants.

ProviderStorageEgressOperationsMonthly total (approx.)
Cloudflare R2$0.60$0.00$18.00 A + $14.40 B~$33.00
AWS S3 Standard$1.15$9.00$25.00 A + $20.00 B~$55.15
Cloudinary (Plus)$89–$99/month (225 credits, includes transforms)included in creditsincluded in credits~$89–$99

Cloudinary is only worth the premium if you need on-the-fly image transformations — resizing, format conversion, face-detect cropping — without writing any code. If you're already handling image optimisation through next/image and serving pre-processed assets, you're paying for features you don't use.

R2 wins on egress-heavy workloads. S3 wins if you're already deep in the AWS ecosystem and want Lambda@Edge, SQS triggers, or tight IAM integration.

What triggers an R2 upgrade on a real Next.js project

Three scenarios push a project out of the free tier faster than expected:

1. Storing pre-generated Open Graph images. If you're generating OG images at build time or on-demand via a route handler and caching them in R2, every unique URL is a PUT. A blog with 2,000 posts means 2,000 Class A ops minimum — well inside the free tier. But if you're also generating per-locale variants, per-date variants, or resized versions, you can hit 10,000+ ops in one deployment.

2. ISR revalidation artifacts. Some teams write JSON snapshot files to R2 as part of their ISR warm-up strategy. Each Sanity webhook → revalidate → write-back cycle = 1 Class A op. At scale this adds up, but you'd need hundreds of publishes per day before it registers.

3. Video uploads routed through Workers. If you're uploading Mux-bound video files through a Cloudflare Worker that stages to R2 first, large multipart uploads count each part as a separate Class A op. A 2 GB video split into 5 MB parts is ~400 ops per upload.

For most Next.js + Sanity setups, R2 stays inside the free tier for months. The upgrade trigger is almost always storage (exceeding 10 GB) rather than operations.

Do you need the Workers Paid plan?

Not for R2 itself. R2's free tier and pay-as-you-go pricing are separate from Workers billing, and R2 buckets can be bound to Workers on the free Workers plan. Where the Workers Paid plan ($5/month) comes in is the compute side: if your Next.js site runs on Cloudflare Workers and outgrows the free Workers request and CPU limits, that's the upgrade you'll hit — not R2. Cloudflare may also ask you to add a payment method when you first enable R2, even if you stay inside the free tier.

For context: Vercel's equivalent, Vercel Blob, charges around $0.023/GB-month for storage plus its own operation and data-transfer fees (simple operations, advanced operations like put()/list(), and Blob data transfer at roughly $0.05/GB in US regions — see Vercel's Blob pricing page). You pay more per gigabyte and for egress, but it's zero-config if you're already on Vercel Pro ($20/month per seat).

When R2 makes sense vs when it doesn't

R2 is worth it when: you're already on Cloudflare for DNS/CDN, your primary cost driver is egress, you want a zero-surprise bill for serving static assets globally, and you're comfortable wiring up S3-compatible SDKs in your Next.js route handlers.

Skip R2 when: you need image transformation logic (use Sanity's native CDN or Cloudinary), you're on Vercel and want zero infra config (use Vercel Blob), or your team isn't familiar with Cloudflare Workers bindings and doesn't want to learn them for a side project.

The free tier is genuinely useful for small to mid-size projects. If you're also running your site on Cloudflare Workers, budget for the $5/month Workers Paid plan once traffic outgrows the free Workers limits.