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
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.
-- 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.
Your own auth
Email/password (argon2id) + Google & GitHub OAuth, database-backed sessions.
Organizations & invites
Org creation, switching, and single-use email invites that expire.
Roles & permissions
Owner / admin / member RBAC, with guards against removing the last owner.
Stripe subscriptions
Per-org checkout, billing portal, and a webhook that syncs state.
Postgres RLS
Real database-level isolation — the differentiator, done right.
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.
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.
For a single developer. Unlimited projects.
- Complete source, yours to modify
- Every feature above
- Future updates
For your whole team or company. Unlimited developers, unlimited projects.
- Everything in Solo
- Use across an unlimited team
- Unlimited client / internal projects
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