Multi-tenant SaaS starter

Tenant isolation your database enforces —
not your WHERE clause.

A production-ready B2B SaaS starter built around the one thing most boilerplates get wrong: keeping one customer's data away from another. Isolation lives in Postgres Row Level Security, so the database refuses to hand over another tenant's rows — even when your code slips.

One-time license · $129 solo / $299 team · full source

Built with Next.js 15· TypeScript· Postgres· Drizzle· Stripe· Tailwind

The silent bug

One forgotten WHERE organization_id is a data breach.

Most starters isolate tenants with a filter in application code. It works — until the one query, join, or new feature that forgets it. Then Customer A sees Customer B's data, and you find out from a support ticket instead of a test. Tenant isolation shouldn't depend on remembering.

How it works

A boundary the database won't let you cross.

Every tenant-scoped table has a Row Level Security policy keyed to the current organization. The row simply isn't visible unless it belongs to the tenant in context — a second line of defense underneath your application code, not a convention you have to remember.

lib/db/rls.sql
-- rows are visible only for the org in context
create policy tenant_isolation on projects
  using (organization_id =
    nullif(current_setting(
      'app.current_org_id', true), '')::uuid);

The part almost everyone gets wrong

RLS is bypassed by the table owner. So TenantForge connects at runtime as a separate, low-privilege database role — never the one that runs migrations. Most “RLS starters” skip this and silently disable their own security. This one ships the split by default.

Proof, not promises

Tested end-to-end, in a real browser.

Signup, creating an org, inviting a member, and starting a Stripe checkout all run in an automated Playwright test — with the emails actually captured. The tenant boundary is verified against a real Postgres, not assumed.

What's included

The boring, essential 80% — already built.

Everything a B2B app needs before it can charge a dollar, wired together and tested end-to-end.

Auth

Your own auth

Email/password (argon2id) + Google & GitHub OAuth, database-backed sessions.

Teams

Organizations & invites

Org creation, switching, and single-use email invites that expire.

Access

Roles & permissions

Owner / admin / member RBAC, with guards against removing the last owner.

Billing

Stripe subscriptions

Per-org checkout, billing portal, and a webhook that syncs state.

Tenancy

Postgres RLS

Real database-level isolation — the differentiator, done right.

Confidence

Tested & typed

End-to-end Playwright smoke test, strict TypeScript, Docker self-host.

Not a demo

A real app you keep building on.

Members, roles, and pending invites out of the box — the example screen below is running code, not a mockup. Delete the sample projects table and follow the same RLS pattern for your own.

TenantForge members screen: an organization with owner, admin and member roles, plus a pending invite.

One-time license

Buy it once. Build on it forever.

No subscription for the starter itself — a one-time license and the full source. Prices in USD.

Team
$299
one-time

For your whole team or company. Unlimited developers, unlimited projects.

  • Everything in Solo
  • Use across an unlimited team
  • Unlimited client / internal projects
Get the Team license

FAQ

Questions a developer actually asks.

What exactly do I get?

The complete source of the starter as a downloadable package — yours to modify and ship. Want the private Git repo with future updates too? Reply to your receipt with your GitHub username and I'll add you.

Is it really one-time, not a subscription?

One-time. You pay once for the license and the code is yours — no recurring fee for the starter itself. (Any Stripe billing you see is the subscription feature your future SaaS can charge with.)

Can I use it for client work?

Yes — build unlimited projects on it. The Solo vs Team split is only about how many developers use the code: Solo is for one developer, Team covers your whole company.

Do I need Docker?

No. It runs against any Postgres, with or without Docker — there's a documented no-Docker setup. Docker is just the fastest way to a local database.

What if it doesn't work for me?

Email me and I'll help — or refund you. It's a new product from one developer, and I'd rather have a happy "no" than an unhappy sale.

Straight with you

TenantForge is new, and it's made by one developer. There are no customer logos or five-star quotes to show you yet — I'd rather not invent them.

What I can point to is the code: the RLS layer is the whole pitch, and it's built the way I'd want my own product's tenant boundary built. If you're evaluating it and something looks wrong, tell me — I'll fix it or refund you.

— the developer behind TenantForge