Picking free object storage in 2026 is harder than the free-GB line suggests

I compared six object storage options that still show up in every “what do I use for file uploads” thread: Cloudflare R2, Backblaze B2, Supabase Storage, Firebase Storage, Storj, and UploadThing. The Reddit-style answers mostly ignore that these products do not meter the same unit, and that the scary bill in a viral month is often egress, not storage.

For an indie app where the nightmare is “my side project hits the front page and my bandwidth bill explodes,” my default pick is Cloudflare R2. Public pricing says internet egress is free for every storage class. That is unusually blunt compared to the rest of this list. The tradeoff is that R2 is S3-compatible but not full-parity S3, and at very high read counts the bill shifts from transfer fees to Class B request charges.

Backblaze B2 is the runner-up I would actually ship if I wanted the most conventional S3 story: 10 GB free storage, free Class A/B/C transactions, and free egress up to 3x your average monthly stored data. After that, outbound is $0.01/GB, and several partner CDNs (including Cloudflare) can make B2-side egress effectively free. The catch is the ratio. Store 10 GB, serve 2 TB, and the 3x rule will not save you.

If you want upload UX more than bucket portability, UploadThing is the ergonomic fork: 2 GB free, unlimited uploads and downloads on the pricing page, first-party Next.js adapters. If you want auth and storage rules in one product, Supabase Storage or Firebase Storage are the platform plays. Neither is what I would pick purely for viral outbound traffic predictability.

You cannot compare these on storage GB alone

Vendors bill storage, egress, API requests, and platform bundles differently. Pick the wrong mental model and you will mis-budget the month your app gets shared everywhere.

Mental modelProvidersWhat burns quota
Storage plus free egressR2, B2 (with caveats), UploadThingGB stored; B2 also cares about download-to-storage ratio
Platform bundleSupabase, FirebaseStorage plus bandwidth plus auth integration
Per-TB egressStorjEgress terabytes; $50/mo minimum from July 1, 2026

S3 compatibility also splits three ways in this set. Full means a native S3-style endpoint with mainstream AWS SDK tooling in normal use. Partial means S3 access exists but parity is incomplete. Adapter required means the normal developer path is provider-native, not S3-first.

You will not get a perfect apples-to-apples table. Use the matrix below as directional, then read the egress section if your app could suddenly serve a lot of downloads.

Free tiers and S3 fit at a glance

ProviderFree tierEgress beyond allowanceS3 compatibilityAuth and SDKsRegionsHard limitsBottom line
Cloudflare R210 GB-month storage, 1M Class A ops, 10M Class B ops, egress free each monthInternet egress free. Paid: $0.015/GB-month storage, Class A $4.50/M, Class B $0.36/MPartial. Some S3 features unimplementedR2 API tokens as S3 creds; AWS SDK examples; Workers bindingsAuto placement; optional location hints (NA, EU, APAC, Oceania)5 TiB object size; 1 write/sec per key; r2.dev not for productionBest if egress-fee shock is the fear. Request-heavy tiny-object workloads can still cost real money.
Supabase StorageFree: 1 GB storage; org egress 5 GB uncached + 5 GB cached. Paid includes 100 GB storage and 250 GB + 250 GB egress before overagePaid overage: $0.09/GB uncached, $0.03/GB cachedPartial. S3 protocol supported; versioning not supportedsupabase-js, Auth + RLS, S3 keys (server keys bypass RLS)One primary AWS region per projectFree projects: 50 MB global file limit; standard uploads to 5 GB; paid up to 500 GB global limitBest when storage should follow auth and RLS. Weak for viral bandwidth predictability.
Firebase StorageCurrent *.firebasestorage.app buckets in us-central1/us-west1/us-east1: 5 GB-months storage, 100 GB/month downloaded, 5K uploads, 50K downloads. Requires Blaze planFalls through to GCS pricing: ~$0.12/GiB general internet egress (first 10 TiB)Adapter required. Normal path is Firebase/GCS-nativeWeb/mobile SDKs, Security Rules, Admin SDK, GCS APIs underneathGCS bucket locations; free allowances tied to eligible US regions above5 TiB object size; 1 write/sec per object; egress quotas can return 429Good inside Firebase. Weak for S3 portability or card-free “free storage.”
Backblaze B2First 10 GB storage free. Free egress up to 3x average monthly stored data. Class A/B/C free; Class D $0.004/10K after 2,500/day freeBeyond 3x stored: $0.01/GB. Partner CDN/compute routes can zero out B2 egressFull. Native S3 API and AWS SDK guidesS3-style app keys; native B2 API optionalUS East, US West, EU Central, Canada East per account (fixed at signup)~500 req/sec default; 100 buckets/account; S3 API returns 503 on throttleStrong value when downloads are not wildly larger than stored data, or behind a partner CDN.
StorjNo durable free tier; 30-day trial (Object Mount materials mention 25 GB for 30 days)$7/TB egress, no API fees. $50 minimum monthly fee effective July 1, 2026Partial. S3 gateway with documented gapsAccess Grants, S3 creds from console, Uplink toolingStandard: globally distributed; Advanced: US SOC 2 Type 2 DCsPaid: 25 TB storage, 100 TB egress, 100 req/sec, 100 buckets/project per projectInteresting per-TB economics if you want distributed storage. Weak for “free tier first.”
UploadThing2 GB storage, 7-day audit log retention, unlimited uploads/downloads on pricing pageNo separate egress meter published; billing is storage-plan-centricAdapter required. Not a raw S3 endpointUPLOADTHING_TOKEN, framework adapters, file-route middleware, UTApiDefault AWS us-west-2; paid plans add region selectionPer-route file type, size, count limits; callback endpoint must stay public; signed URLs max 7 daysFastest Next.js upload ship. Weakest for raw bucket control or S3 portability.

Among these six, only R2 really behaves like a viral-safe object store on bandwidth by default. B2 can get close behind a partner CDN. UploadThing looks equally gentle on public pricing, but it is a managed upload layer, not a general-purpose bucket.

If decentralized positioning itself is the requirement, Filebase advertises 5 GB pooled free storage with free object egress, and Akave markets zero-egress S3-compatible storage without a similarly meaningful free tier in the materials I read. I did not fully review either here.

Egress economics when traffic spikes

The table below is egress only. It ignores included free quotas unless noted, excludes storage and request charges, and uses round 100 GB / 1 TB / 10 TB months for readability. Firebase’s underlying GCS pricing is quoted in GiB/TiB, so real invoices will differ slightly.

Scenario100 GB/mo1 TB/mo10 TB/moNotes
Cloudflare R2$0$0$0Public internet egress free. Storage and requests billed separately.
Supabase uncached overage$9$90$900Paid-plan $0.09/GB uncached; ignores included quota
Supabase cached overage$3$30$300Paid-plan $0.03/GB cached; ignores included quota
Firebase raw GCS overage$12$120$1,200GCS ~$0.12/GiB general internet; simplified as $0.12/GB
Firebase with eligible-bucket allowance$0$108$1,188Subtracts 100 GB/month free download for current bucket family
Backblaze B2 at 100 GB stored$0$7$973x rule: 300 GB free egress, then $0.01/GB
Backblaze B2 at 1 TB stored$0$0$703 TB free egress with 1 TB stored
Storj egress only$0.70$7$70$7/TB egress; excludes storage and $50 minimum
UploadThing (public pricing)$0$0$0No separate bandwidth meter on pricing page; storage plan still applies
xychart-beta
    title "Representative viral-spike egress bill for a 10 TB month"
    x-axis ["R2","Supabase cached","Supabase uncached","Firebase adjusted","B2 at 100 GB stored","Storj","UploadThing"]
    y-axis "USD" 0 --> 1200
    bar [0,300,900,1188,97,70,0]

The chart is not saying Storj always beats Backblaze or UploadThing is “better storage” than R2. The shape of viral risk differs sharply. R2 and UploadThing mostly remove the bandwidth line item. Backblaze makes egress small but ratio-sensitive. Storj keeps per-TB egress low but adds a billing floor. Supabase and Firebase can hurt if your app turns into a download hose.

Two subtleties worth separating.

R2 changes the failure mode from egress to requests. Cloudflare’s own pricing example for hosting 100,000 small files with 10 million object reads per day lands around $104.40/month in Class B charges while egress stays free. R2 is excellent for “my CDN transfer bill exploded,” not literally free for high-read, tiny-asset workloads.

Backblaze’s free egress is storage-coupled unless you use a listed partner CDN or compute route. Store little, stream a lot, and the 3x number is what matters. Already on Cloudflare, Fastly, or bunny.net? The B2-side egress risk drops a lot.

Firebase has its own fork: front GCS with Cloud CDN and Google says storage transfer charges can be waived, but that is no longer “just Firebase Storage pricing.” You are now running a multi-product CDN architecture with cache-fill economics. Valid, but less simple than R2’s native no-egress-fee position.

What the free tiers actually cost you later

Cloudflare R2: best viral-bandwidth predictability, watch request pricing

R2’s free tier is generous enough for side projects: 10 GB-month, a million Class A operations, ten million Class B operations, and egress that does not meter on the public page. Paid storage at $0.015/GB-month is reasonable.

The S3 story is real but incomplete. Cloudflare’s compatibility page lists unimplemented operations. For typical app uploads and signed delivery, that is usually fine. For exotic S3 tooling, test before you commit.

My main warning is request economics, not egress. Asset hosts with millions of small reads can still see a meaningful bill. Budget both dimensions.

Backblaze B2: best mainstream S3 parity, ratio-sensitive egress

B2 is what I recommend when someone says “I want S3, but cheaper, and I will use the AWS SDK.” Ten gigabytes free forever, free Class A/B/C transactions, and the 3x egress rule are unusually friendly for small teams.

The storage-to-download ratio is the whole game. Viral file delivery from a small bucket without a partner CDN is exactly the scenario where B2’s free egress stops feeling free. Put Cloudflare or another partner in front and the picture changes.

Account region is chosen at signup (US East, US West, EU Central, Canada East) and cannot be moved later. Plan that once.

Supabase Storage: best with Supabase Auth and RLS, expensive uncached egress

Supabase Storage shines when you already run Supabase Auth, Postgres, and RLS. Browser uploads through supabase-js, JWT-backed session S3 access that respects policies, and server S3 keys when you need them (knowing server keys bypass RLS).

Free tier is tight: 1 GB storage and 5 GB + 5 GB org egress. Paid overage at $0.09/GB uncached and $0.03/GB cached means CDN hit ratio matters a lot. A viral month on uncached delivery gets expensive fast.

S3 access exists but is partial. No versioning. Fine for app storage, not a drop-in replacement for every S3 workflow.

Firebase Storage: good Firebase ergonomics, Blaze required, GCS underneath

Firebase Storage is the obvious pick when you already live in Firebase Auth, Security Rules, and the mobile/web SDKs. Direct client uploads with rules tied to identity is a nice developer experience.

Current docs require the Blaze plan even though usage allowances still exist. That is not a clean no-card free storage story anymore.

Free allowances for the current *.firebasestorage.app bucket family are tied to us-central1, us-west1, and us-east1. Beyond that, you are in GCS pricing land. Treat Firebase as a platform choice, not a generic bucket.

Storj: interesting per-TB model, trial-only free tier, billing floor coming

Storj charges $7/TB for storage and $7/TB for egress with no API fees. The decentralized architecture is the point, not a footnote.

For indie “free tier first” evaluation, the picture is weaker. Durable free object storage is basically gone (30-day trial). A $50 minimum monthly fee starts July 1, 2026. I would only pick Storj here if distributed storage is a product requirement, not because it won a free-GB comparison.

UploadThing: fastest Next.js ship, not a portable S3 bucket

UploadThing is not raw object storage. It is a managed upload and delivery product with first-party Next.js adapters, file-route middleware for auth, and callbacks that behave like webhooks.

Two gigabytes free, unlimited uploads and downloads on the pricing page, no published egress meter. That is attractive when the problem is “ship safe uploads this week,” not “own a bucket I can move anywhere.”

The docs are explicit: do not rely on raw storage-provider URLs because files may move between providers. Your callback endpoint must stay publicly reachable. Signed URL expirations cap at seven days.

Integration patterns for Vercel, Netlify, Next.js, and Node

Do not proxy large binary uploads through your hosting function unless the files are tiny. Vercel Functions cap bodies at 4.5 MB. Netlify Functions allow 6 MB buffered payloads, but binary data is Base64-encoded, so the effective binary limit is roughly 4.5 MB again.

Default architecture: browser to object store direct upload, with your server only minting a presigned URL or upload token.

flowchart LR
    U[User browser] --> A[App auth/session]
    A --> S[Small signer endpoint on Vercel, Netlify, or Node]
    S --> T[Presigned URL or upload token]
    U --> D[Direct upload to object store or UploadThing ingest]
    D --> C[CDN or signed delivery URL]
    C --> U
StackPatternBest-fitting providers
VercelRoute Handler signs uploads only; secrets in env vars; browser uploads directR2, B2, Storj, Supabase S3, UploadThing, Firebase client SDK
NetlifyFunction as signer only, not upload proxySame as Vercel
Next.jsRoute Handlers or Server Actions as signer; UploadThing has App Router support; Supabase has Storage quickstartsUploadThing, Supabase, any S3 backend, Firebase web SDK
Generic NodeAWS SDK v3 against S3-compatible endpoints; Firebase Admin for GCS flowsR2, B2, Storj, Supabase S3, Firebase Admin, UploadThing
Static sitesNever ship raw S3 secrets to the browser; use signed URLs or a tiny signerUploadThing, Firebase, Supabase, or public-read R2/B2 with signer for writes

A generic S3-compatible signer for Next.js or any Node host. Provider differences are mostly endpoint, region, and forcePathStyle (Supabase wants true; R2 uses region auto).

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const s3 = new S3Client({
	region: process.env.S3_REGION ?? 'auto',
	endpoint: process.env.S3_ENDPOINT!,
	forcePathStyle: process.env.S3_FORCE_PATH_STYLE === 'true',
	credentials: {
		accessKeyId: process.env.S3_ACCESS_KEY_ID!,
		secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!
	}
});

export async function POST() {
	const key = `uploads/${crypto.randomUUID()}.bin`;

	const url = await getSignedUrl(
		s3,
		new PutObjectCommand({
			Bucket: process.env.S3_BUCKET!,
			Key: key,
			ContentType: 'application/octet-stream'
		}),
		{ expiresIn: 60 }
	);

	return Response.json({ key, url });
}

For Supabase-first apps, uploading through supabase-js under your auth and RLS model is usually simpler than building a separate signer.

const file = input.files?.[0];
const { data, error } = await supabase.storage.from('avatars').upload(`public/${file.name}`, file, {
	cacheControl: '3600',
	upsert: false
});

For UploadThing, define a file route, auth in middleware, ship with the generated client helpers.

import { createUploadthing, type FileRouter } from 'uploadthing/next';

const f = createUploadthing();

export const ourFileRouter = {
	imageUploader: f({ image: { maxFileSize: '4MB', maxFileCount: 1 } })
		.middleware(async ({ req }) => {
			const user = await auth(req);
			if (!user) throw new Error('Unauthorized');
			return { userId: user.id };
		})
		.onUploadComplete(async ({ metadata, file }) => {
			return { uploadedBy: metadata.userId, fileKey: file.key };
		})
} satisfies FileRouter;

Who should pick what

flowchart TD
    start[Need object storage] --> egressQ{Viral egress fear?}
    egressQ -->|Yes| r2[R2 or UploadThing if managed uploads]
    egressQ -->|No| s3Q{Need S3 portability?}
    s3Q -->|Yes| b2r2[Backblaze B2 or R2]
    s3Q -->|No| authQ{Auth and rules integrated?}
    authQ -->|Yes| platform[Supabase or Firebase]
    authQ -->|No| nextQ{Next.js upload DX priority?}
    nextQ -->|Yes| ut[UploadThing]
    nextQ -->|No| b2r2

Hobby projects and solo devs: R2 if the nightmare is bandwidth bill shock. UploadThing if you are on Next.js and want uploads working tonight. B2 if you want the most textbook S3 setup and your download volume is not wildly larger than what you store. Do not treat Firebase as card-free storage; Blaze is required.

Startups: R2 for predictable viral-month bandwidth. B2 behind Cloudflare if you want conventional S3 plus partner egress. Supabase Storage if you are already on Supabase Auth and RLS. UploadThing for TS teams that would rather not own presigned URL plumbing. Firebase only if the rest of the stack is already Firebase.

Teams already on Firebase: Firebase Storage is the ergonomic default. Front with Cloud CDN if GCS egress becomes the line item, and accept that you are now operating CDN cache behavior, not just a bucket.

For a bootstrapped web app I would ship R2, wire direct browser uploads through a small signer endpoint on day one, and keep B2 plus Cloudflare in mind as the first fork if I need fuller S3 parity or already run B2 elsewhere.

Gaps in the public docs

Supabase free-plan docs show bandwidth quotas but not a clear free-plan overage schedule like the paid tables. The egress scenarios above use paid overage rates when modeling what happens after you outgrow free.

Firebase pricing depends on bucket family, region, and destination geography. The numbers here use the current *.firebasestorage.app allowance and GCS general internet transfer as a reference case, not a universal invoice prediction.

Storj’s $50 minimum is on the public pricing page, effective July 1, 2026.

UploadThing does not publish a separate egress or request meter. Bandwidth-risk analysis here follows what the pricing page shows today, not a low-level billing spec.

Sources

Cloudflare R2

R2 pricing
S3 API compatibility
AWS SDK for JavaScript v3
R2 limits

Backblaze B2

B2 pricing
AWS SDK for JavaScript with B2
CDN and compute integrations

Supabase Storage

Storage size usage
Egress usage
S3 authentication
Storage guide

Firebase Storage

Firebase pricing
Cloud Storage for Firebase
Usage limits
Google Cloud Storage pricing

Storj

Storj pricing
S3 compatibility

UploadThing

UploadThing pricing
UploadThing docs
Next.js App Router setup

Hosting platforms

Vercel function limitations
Netlify Functions