You typed "Next.js SaaS starter Supabase" because you've half-decided the stack: Supabase for auth and database, done. SaaS Starter doesn't ship that — it ships Clerk + Prisma over plain Postgres. Rather than pretend that's irrelevant to you, this page puts the two choices side by side for a real buying decision: where Clerk + Prisma wins, where Supabase genuinely wins, and the exact steps to run Supabase's Postgres behind Prisma if you want the best of both.
If you want row-level security as your authz model, realtime on your tables, or one open-source vendor for auth + DB + storage, Supabase is the right call — and a Supabase-native free starter beats bending this one. Go build on vercel/nextjs-subscription-payments with my blessing.
If you want a portable database you can move off any host, generated types across the app, and auth as a swappable surface with teams and MFA built in, Clerk + Prisma is why SaaS Starter is built the way it is. And you're not locked out of Supabase either way — because Supabase is Postgres, you can put its database behind Prisma in about 20 minutes. The steps are below.
Both are good. They optimise for different things: Clerk is a hosted identity product that hands you teams, MFA and polished UI on day one; Supabase Auth is an open-source, self-hostable layer that lives next to your Postgres and pairs with row-level security. Pricing tiers move constantly on both — treat the numbers below as direction, and check each vendor's live pricing page before you commit.
| Dimension | Clerk (SaaS Starter default) | Supabase Auth |
|---|---|---|
| Model | Hosted identity service | Open-source (GoTrue), self-hostable |
| Organisations / teams | Built-in (orgs, roles, invites) | You model it in tables + RLS |
| MFA | Built-in (TOTP, SMS) | TOTP supported |
| Pre-built UI | Drop-in React components | Auth UI helpers, more DIY |
| SSO / SAML | Yes (higher tiers) | Yes (Pro/Team add-on) |
| Where the session lives | Clerk-issued, verified in middleware | JWT you verify, ties into Postgres RLS |
| Free tier (directional — verify) | ~10,000 MAU, then per-MAU | ~50,000 MAU, then per-MAU |
| Couples auth to your database? | No — separate service | Yes — auth.users lives in your DB |
| Swap it out later | Isolated in src/lib/auth.ts | Woven into RLS policies |
The honest read: if you'll sell to teams soon, Clerk's built-in organisations save real weeks. If your authorization model is going to be row-level security enforced in Postgres, Supabase Auth is the more natural fit because the user id it issues is already the one your RLS policies key on. Neither is "better" in the abstract — they're better for different products.
This is the deeper of the two decisions, because it's the one you can't cheaply undo. Prisma is a query builder and migration tool over plain Postgres. The Supabase client (supabase-js) is an SDK over PostgREST, realtime and RLS that assumes the Supabase platform underneath.
| Dimension | Prisma / Postgres (SaaS Starter) | Supabase client |
|---|---|---|
| Runs on any Postgres host | Yes — Neon, RDS, Supabase, self-host | Tied to the Supabase platform |
| Type safety | Generated Prisma types, end to end | Generated types, less ergonomic |
| Migrations | Prisma Migrate, versioned | SQL migrations / dashboard |
| Authorization | In app code (server components/actions) | Row-level security, in the DB |
| Realtime subscriptions | Not built in | First-class |
| Auto REST/GraphQL API | You write the routes | PostgREST, automatic |
| Lock-in risk | Low — it's just Postgres | Higher — platform features couple you |
Read the two green columns and you see the trade in one line: Prisma optimises for portability and type safety; the Supabase client optimises for velocity and in-database security. If you love RLS and realtime, that's a genuine reason to go Supabase-native and not fight it. If you'd rather never be unable to move your database, Prisma is the reason SaaS Starter is built the way it is.
Three reasons, stated as trade-offs rather than dogma — because for a different product the opposite choice is correct:
1. Database portability, no platform lock-in
Prisma over plain Postgres means DATABASE_URL can point at Neon, RDS, Railway, a self-hosted box — or Supabase itself. Your schema and data move with one env var. Nothing in src/ assumes a specific host. That's the single biggest reason: a boilerplate you can't migrate off is a liability the day the host's pricing changes.
2. Auth as an isolated, swappable surface
Every auth call goes through src/lib/auth.ts (getCurrentUser, requireUser, requireAdmin, syncUser). Swapping Clerk for another provider is a bounded edit to one file, not a rewrite. Contrast with RLS-based auth, which by design threads through every table policy.
3. Generated types across the whole app
The Prisma client gives you a typed User model consumed by 23 call-sites in the admin panel and dashboard, so a schema change surfaces as a TypeScript error before it's a runtime bug. Teams built in is Clerk's job; typed data is Prisma's.
Where this bites us: SaaS Starter has no realtime and no row-level security — authorization is enforced in server code, not the database. If a hostile query ever bypassed the app layer, there's no RLS backstop. For most single-tenant SaaS that's fine; if you're building something where DB-enforced tenant isolation is a security requirement, Supabase's RLS is a real advantage we don't match. Said plainly so it's not a surprise.
A vendor page that never recommends the alternative isn't being honest. Here's when I'd tell you to skip SaaS Starter and go Supabase-native:
RLS is your authorization model
You want tenant isolation enforced in the database, not just in app code. That's Supabase's home turf; fighting it with Prisma-only authz is swimming upstream.
Realtime is a core feature
Live cursors, presence, collaborative state. Supabase Realtime gives you subscriptions on Postgres changes out of the box; SaaS Starter would have you build that layer.
One open-source vendor, self-hostable
Auth + DB + storage + edge functions from one platform you can self-host if you ever need to. That consolidation has real operational value.
You're cost-sensitive at low scale
Supabase's free auth tier is more generous on MAU than Clerk's. If you'll sit below the paid threshold for a while, that's money saved — factor it in honestly.
If two or more of those are true for you, the right free starting point is vercel/nextjs-subscription-payments (Next.js + Supabase Auth + Stripe, MIT). Buy nothing here; that's the honest recommendation.
Here's the both-worlds path a lot of people actually want: keep SaaS Starter's Clerk + Prisma app, but host the database on Supabase (managed Postgres, backups, a nice SQL editor). Because Supabase is plain Postgres, this is a connection-string change, not a rewrite. About 20 minutes.
1. Copy both connection strings from Supabase
In Project Settings → Database, grab the pooled string (Supavisor, transaction mode, port 6543) for the app, and the direct string (port 5432) for migrations.
2. Set both in .env
# pooled — used by the running app (serverless-safe) DATABASE_URL="postgresql://postgres.[ref]:[pwd]@aws-0-[region].pooler.supabase.com:6543/postgres?pgbouncer=true&connection_limit=1" # direct — used only by Prisma Migrate / db push DIRECT_URL="postgresql://postgres.[ref]:[pwd]@aws-0-[region].pooler.supabase.com:5432/postgres"
The ?pgbouncer=true flag tells Prisma not to use prepared statements the transaction pooler can't hold; connection_limit=1 keeps serverless functions from exhausting the pool.
3. Add directUrl to the datasource
// prisma/schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") directUrl = env("DIRECT_URL") }
Migrations run over the direct 5432 connection; the app runs over the pooled 6543 one. This one-line addition is the whole trick.
4. Push the schema and generate
npx prisma db push # or: npx prisma migrate deploy
npx prisma generate
SaaS Starter's User, WaitlistEntry and other tables are now created inside your Supabase database. Nothing in the app code changed — Prisma is talking to Postgres and Supabase is simply the host.
5. Decide what else Supabase is for
If you only wanted managed Postgres, you're done — auth stays on Clerk. If you also want Supabase Auth, Storage or Realtime, add supabase-js alongside Prisma and route those features through it. Just go in eyes-open: you're now running two systems, and the coexistence section below is the honest cost of that.
Coexistence caveat: Clerk and Supabase Auth both want to own "who is the user". Run both and you've signed up to keep two identity systems in sync — a common source of subtle bugs. The clean setups are: (a) Clerk for auth + Supabase only as the Postgres host (the guide above), or (b) go fully Supabase-native and don't buy this kit. Running Clerk auth and Supabase auth together is the configuration I'd steer you away from unless you have a specific reason.
Whichever database host you point Prisma at, SaaS Starter's admin panel comes wired. It queries the User model to compute live MRR and plan splits — the thing neither the free official starter nor the Supabase subscription template ships. Here's the shape of it (poke the real thing on the live demo):
Admin → Metrics /admin/metrics ────────────────────────────────────────────────────── MRR $2,146 Active subs 37 Users (total) 412 New this month 28 ────────────────────────────────────────────────────── Plan split FREE ■■■■■■■■■■■■■■■■■ 361 PRO ■■ 44 BUSINESS ▪ 7 ────────────────────────────────────────────────────── Figures above are illustrative demo data, not real revenue.
The layout is real; the numbers are demo seed data, labelled as such — no invented revenue claims. The panel is driven by Prisma queries against whatever Postgres you connected, Supabase included.
Not by default — it ships Clerk for auth and Prisma over plain Postgres. But since Supabase is just Postgres, you can point Prisma at a Supabase database in about 20 minutes using the guide above. Auth stays on Clerk unless you deliberately add Supabase Auth too.
Yes, but you're then running two things: Supabase Auth owns the auth.users table and issues the JWT; Prisma manages your app tables. You keep them in sync by storing the Supabase user id as a foreign key and creating the app-side row on first sign-in. It works — it's just more moving parts than the default of Clerk owning identity and Prisma owning everything else.
If Supabase-native is what you want, you should — vercel/nextjs-subscription-payments is the honest pick and it's free. SaaS Starter is worth paying for when you want the Clerk + Prisma trade (portability, teams, typed data) and the finished extras the free templates skip: admin MRR panel, 4 email templates, 8 locales, 45 tests. The full free-vs-paid maths is on our free starter page.
That's exactly why the guide sets a separate DIRECT_URL. Prisma Migrate needs a direct connection because the transaction pooler doesn't hold the prepared statements and advisory locks migrations use. App queries go through the pooler; migrations go direct. Set both and it just works.
The auth, data and billing layers are written up in /docs/architecture, and the whole kit is compared against the free and paid alternatives in the honest 2026 roundup, which publishes the real npm run audit output.
If the portability-and-teams trade is what you want, that's SaaS Starter — and you can still put the database on Supabase with the 20-minute guide above. If RLS and realtime are the point, go build free on the Supabase-native starter instead; no hard feelings. 30-day refund either way.
One-time payment · 30-day refund · Instant GitHub access · See the live demo