When you’re building an indie app or Android product, the sticky question usually isn’t “Is Cloudflare better than Firebase?” It’s a simpler one: where should this thing live?
Files, user records, and a marketing site all sound like “storage.” Under the hood they’re three different shelves. Brand names are just labels on those shelves. Separate the shelves first, then pick a vendor.

Three “stores” that are not the same thing
A WeChat-style analogy helps:

| Everyday name | What you keep | Feels like… | Cloudflare | Firebase |
|---|---|---|---|---|
| Place for files (object storage) | Images, video, PDFs | Photos/videos in chat | R2 | Storage |
| Place for records (database) | Names, orders, text fields | Friend list / message rows | D1 / KV | Firestore / RTDB |
| Place for the site shell (static hosting) | HTML / CSS / JS | Mini-program shell / landing page | Pages | Hosting |
In short:
- Object storage: fetch a whole file by key — like a drive.
- Database: query rows by conditions — like an address book.
- Hosting: open a URL and get a page — like a CDN-backed site.
A full app often needs all three. Don’t use a photo bucket as a user table, and don’t expect static hosting to be your album.
Static sites: compare Pages with Hosting — not Workers
People often compare Workers (run code at the edge) with Firebase Hosting (static hosting). That’s the wrong shelf.
- Hosting / Pages: push site files to the edge so people can open a URL.
- Workers: run your logic (APIs, auth checks, assembled responses). Not the shelf for “put the homepage here.”
So for a static site, compare Firebase Hosting vs Cloudflare Pages. For APIs / backend logic, look at Workers (on Firebase you often add Cloud Functions).

On free tiers, Pages is usually wider
| Cloudflare Pages | Firebase Hosting (Spark) | |
|---|---|---|
| Storage | Notes say unlimited | ~10 GB |
| Traffic | Notes say unlimited | ~360 MB/day (then metered) |
| Free subdomain | *.pages.dev | *.web.app |
No slogans needed: for a landing page, docs site, or simple marketing site, Pages free traffic looked wider. If you’re already deep in Firebase (auth + Firestore), Hosting is still convenient — just watch the ~360 MB/day line.
Workers free tier has its own request limits (notes often cite ~100k/day). That’s a “running code” bill — don’t mix it with static traffic.
Photos: R2 and Firebase Storage don’t share the same on-ramp
Avatars, galleries, attachments — that’s object storage.
From the notes (2026-08; Storage policy from then-current firebase.google.com/pricing):
| Cloudflare R2 | Firebase Storage | |
|---|---|---|
| Usable on free tier? | Yes; notes cite ~10 GB storage, egress-friendly free tier, monthly op limits | Spark marks Storage Not applicable |
| To use it | Sign up and stay within free quotas | Need Blaze (pay-as-you-go) + a card; Blaze has its own free allowances, but “zero-card free start” is gone |
For indies this often matters before SDK taste: Storage isn’t available on Spark; R2 can get “store images” working inside a free tier.
Exact Blaze free GB/ops: use today’s pricing page. Example traffic math in the notes is hypothetical — not your real bill.
Login and storage are two jobs
“Users sign in with Google, so everything must live on Firebase” is a common mix-up.
- Login (Google Sign-In): proves who you are and gives a verifiable ID token.
- Storage: images and user tables can live on Cloudflare (R2 / D1) or elsewhere.

A workable pattern:
- App signs in with Google and gets an ID token
- Send the token to a Cloudflare Worker
- Worker verifies the token with Google
- On success, read/write R2 (files) or D1 (structured data)
One line: Auth can be Google; the warehouse can be Cloudflare. They don’t fight.
In similar indie Android / app setups, people often split “login here, storage there” when counting cost — instead of defaulting to one full vendor stack.
A common indie stack
If the goal is roughly: Android app + Google login + user uploads + a bit of structured data, the notes keep landing on:
| Need | Common pick |
|---|---|
| Prove identity | Google Sign-In (auth can start free) |
| Backend API | Cloudflare Workers |
| Images / files | Cloudflare R2 |
| User / business rows | Cloudflare D1 (SQL); cache/session via KV |
| Site / landing | Cloudflare Pages |
Be honest on cost: within free quotas and without heavy AI burn, you can often start near-free besides the domain. Domains you usually still buy. Quotas change and projects grow — don’t write “forever free.”
Quotas are usually shared per account
Cloudflare free quotas are mostly one pool per account, not a fresh full allotment per project:
- Multiple Workers share daily request limits
- Multiple R2 buckets share storage + ops
- Multiple D1 databases share total storage (instance caps too)
Pages traffic looked relatively generous per project in the notes; build counts and other limits may still be account-wide. Opening another side project doesn’t always mean “another full free package.”
Quick lookup
| You need… | Look at first | Notes |
|---|---|---|
| Static site, fear blowing free traffic | Cloudflare Pages | Pairs with Hosting, not Workers |
| Already deep in Firebase | Firebase Hosting + ecosystem | Easy integration; watch daily Hosting traffic |
| User uploads, want a free-tier start | Cloudflare R2 | Storage unavailable on Spark (per notes) |
| Structured user / business data | D1 or Firestore | Realtime needs change the taste |
| Realtime sync / listeners | Firestore / RTDB | Not the same model on CF |
| Edge API, light logic | Workers | Don’t treat as a static-hosting substitute |
| Google login + low-cost files + tables | Sign-In + Workers + R2 + D1 | Split auth and storage |
Close
Ask three questions:
- Am I storing files, records, or a website?
- Am I comparing hosting or running code?
- On the free tier, can I turn this on, or do I need a card?
Once the three shelves are clear, Cloudflare vs Firebase stops being tribal — it’s shelf matching.
(If you’re also splitting storage for an indie app, run the math on your own traffic and uploads — more useful than arguing brands.)