MW
Home Blog Cloudflare D1 vs Supabase for indie SaaS — six months in production

Cloudflare D1 vs Supabase for indie SaaS — six months in production

Two strong choices, two very different bets. After six months running both in production, here's where each one wins and which one I'd reach for first in 2026.

Mahesh Waghmare
Mahesh Waghmare
8 min read
Share:
This is a comprehensive guide based on real-world experience and best practices from production projects.

CLOUDFLARE D1 VS SUPABASE FOR INDIE…

Advertisement

I run 46 sites on Cloudflare and one paying SaaS on Supabase. They’ve both been in production for over six months. People keep asking which one to pick for a new indie SaaS, and the honest answer is “depends on three things you can actually quantify.”

This post is that answer.

The three questions that decide it

Everything else in this post is the reasoning behind that recommendation. The short version: D1 is a database. Supabase is a backend. They compete only at the database layer; above that, you’re comparing a sharp tool against an entire workshop.

Cost — at indie-SaaS scale

This is where most decisions actually happen, so let’s start there.

D1 free tier: 5 GB storage, 5 million row reads/day, 100k row writes/day. For a site doing 10k page views/day with a content-fetch-heavy pattern, you’ll fit comfortably. Past the free tier: $0.75 per million reads, $1 per million writes, $0.75/GB stored. Workers Paid plan is $5/month and includes generous bumps.

Supabase free tier: 500 MB database, 1 GB file storage, 5 GB egress, 50k monthly active users on auth. Past free: Pro starts at $25/month, includes 8 GB database, 100 GB egress, $10 of compute credits.

The cost gap closes when you start paying for either. The cost gap opens when you need multiple databases (D1 lets you create them freely on the Workers Paid plan; Supabase wants a separate project per database, each with its own $25/month minimum if not on free tier).

Latency — where D1 wins and Supabase doesn’t try

D1 runs at the edge. Your database is in the same region as your Worker, which is in the same region as your user. P95 query latency for a typical read is under 5ms.

Supabase runs your database in one region. If you put it in Frankfurt and your user is in Mumbai, you eat the round trip. They have read replicas on Pro+, but the writes always go through the primary.

For a content site, this is decisive. D1 makes your blog posts faster than the static HTML they’re rendered into.

For a transactional SaaS, it depends. If your user signs up once in Mumbai and uses your dashboard from Mumbai, Supabase in Singapore is fine. If your users are global and every interaction reads from the DB, D1’s edge model becomes a real advantage.

D1 latency feels like reading from cache. Supabase latency feels like reading from a database. You notice the difference at the second click, not the first.

— six months of empire receipts

SQL ergonomics — Supabase wins, but it matters less than you think

Supabase is Postgres. You get the full SQL surface: JSON columns, full-text search, real foreign keys, triggers, stored procedures, geographic types, the lot. Their migration tooling (supabase db diff, supabase migration new) is excellent.

D1 is SQLite under the hood. SQLite is more capable than people give it credit for — it has JSON, FTS5 for full-text, decent recursive CTEs, generated columns, partial indexes. But it isn’t Postgres. No LATERAL, no native JSON-path query operators, no RETURNING in older versions (it works in D1 now, but you’ll find tutorials assuming Postgres).

For a content-heavy site (mw.com, marathi.community), SQLite is more than enough. For a SaaS with complex reporting, you’ll feel the cap.

What Supabase includes that D1 doesn’t

This is where the comparison stops being apples-to-apples.

Supabase ships auth out of the box — email/password, OAuth providers, magic links, row-level security. With D1, you build that yourself or wire in auth.surror.workers.dev (my approach) or Clerk / Lucia / WorkOS.

Supabase ships storage — uploaded files, image transforms, signed URLs. With D1 you use R2 yourself and sign your own URLs.

Supabase ships realtime — Postgres LISTEN/NOTIFY over WebSockets. With D1 there’s no equivalent; you’d lean on Durable Objects or Workers WebSockets.

Supabase ships edge functions — Deno-runtime Lambdas at the edge. Workers is the same idea, except your edge runtime is the whole stack, not a sidecar.

The lock-in dimension

Both are sticky in different ways.

D1 is SQLite-compatible — your schema migrates to local SQLite, Turso, or anywhere else with minor changes. The Cloudflare-specific surface is the binding (env.DB.prepare()...); your data and schema are portable.

Supabase is Postgres-compatible — your database migrates anywhere with pg_dump. The Supabase-specific surface is auth schemas, RLS policies, storage buckets; all of that you’d rebuild on Auth0/Clerk/AWS/whatever.

Neither one is meaningfully locked-in at the database layer. The lock-in is in the auth and storage layers, where Supabase has more to lose.

What I’d pick in 2026

For each of the empire’s actual surfaces:

  • mw.com, marathi.community, the 30-something content sites — D1. Edge latency wins, schema is trivial, no auth needed beyond a static signup form.
  • himcq.com (paid SaaS) — Supabase, with the database in ap-south-1 (Mumbai) because the audience is concentrated. The hosted auth was worth not building it.
  • tools.town (the 7 SKUs) — D1 per tool. Each one is tiny, each one’s data is small, the per-tool isolation is a feature.
  • anything with realtime collaboration — Supabase, full stop. Even though I could build Y.js sync on Durable Objects, I haven’t, and that’s the point.

D1 is the right call when the database is just storage. Supabase is the right call when the database is the spine of a product.

— me, after six months of both

The decision shortcut

I run both. I keep both. They solve different problems. The honest mistake isn’t picking the wrong one — it’s picking either one because the marketing was good. Pick the one whose default answer to your hard question is the answer you’d otherwise build yourself.

Get weekly notes in your inbox

Practical tips, tutorials and resources. No spam.