Multi-Tenant SaaS: Auth, Roles, and Stripe Billing Without the Pain
By Nikola, Founder at Zerox
By Nikola, founder at ZEROX. We build SaaS platforms, internal tools, and customer portals for B2B companies and agencies, so this is the layer we wire in on most projects. Last updated April 2026.
Every SaaS founder budgets time for the features that demo well and almost none for the layer beneath them: who owns what data, who may see it, and how you charge for it. Multi-tenant SaaS billing, account architecture, roles, and Stripe subscriptions are the plumbing that never makes the pitch deck and always decides whether you can scale or have to rebuild. This post is for technical founders who want that layer right the first time.
None of it is glamorous, and all of it is costly to change later. We wire it in from day one, not after the first enterprise customer starts asking hard questions.
Pick your tenancy model with your eyes open
The first decision is how you isolate one customer's data from another's. Three approaches are common, and the right one depends on your compliance needs and scale, not on fashion.
| Model | Isolation | Best for |
|---|---|---|
| Row-level (shared tables, tenant_id column) | Logical | Most B2B SaaS, fast to build, cheap to run |
| Schema-per-tenant | Stronger | Mid-market with per-customer customization |
| Database-per-tenant | Physical | Regulated data, large enterprise, noisy-neighbor risk |
For most B2B products, row-level isolation with a tenant_id (or org_id) on every table is the right default: simple, scales far, and cheap on cloud Postgres. The risk is equally simple, one forgotten org filter leaks data across customers. Do not leave that to discipline: enforce it with row-level security in the database, or a query layer that refuses any tenant-scoped query without a tenant in scope. Make the safe path the only path.
Do not choose database-per-tenant because it feels safer. It multiplies your migration, backup, and connection-pool work by the number of customers you have. Reserve it for when a contract or regulator requires physical separation.
Model orgs, users, and roles as separate things
The most common data-model mistake we see is fusing the user and the account. A user is a person; an organization is the paying account; membership links them and carries the role. Keep them separate and most future headaches disappear.
A clean baseline looks like this:
- Organizations own data, subscriptions, and settings. They are the unit you bill.
- Users are people who authenticate. One human, one identity.
- Memberships join a user to an org and carry the role, so one user can belong to several orgs at once.
- Roles (owner, admin, member, billing, read-only) live on the membership, never on the user globally.
- Invitations are their own object with a token and an expiry, so adding a teammate never means sharing a password.
The moment one user belongs to two customers, an agency with several clients, a contractor across accounts, a global user role breaks. Memberships cost nothing on day one and a painful migration later.
Treat permissions as a layer, not a column
Roles are a label; permissions are the rules, and they belong in one place every request passes through, not scattered across route handlers. Centralize a single check, can(user, action, resource), and call it everywhere: one file to audit when a customer asks who can delete something, and one place to add granular rules when a role is not enough.
Two rules save pain later. Enforce permissions on the server, a hidden button is UX, not security. And resolve the tenant on every request from the session or token, never from a value the client can set. Most multi-tenant leaks are not clever attacks; they are an ID read from a request body that nobody scoped.
Multi-tenant SaaS billing with Stripe, done properly
Billing is where corners get cut most, because the happy path is easy and the real world is not. Done properly, multi-tenant SaaS billing treats Stripe as the source of truth for subscription state and mirrors just enough of it into your database to decide fast.
The pieces that actually matter:
- One Stripe customer per organization, not per user, with the stripe_customer_id stored on the org.
- Webhooks are the backbone, not an afterthought. Subscription status, plan changes, and payment outcomes arrive as events. Verify the signature, keep handlers idempotent, and let the webhook, not the checkout redirect, flip an account to active.
- Handle failed payments deliberately. Stripe's dunning retries the card; you decide what a past-due account can still do and when it downgrades. Silence means free service or angry churn.
- Use Stripe's proration for plan changes rather than your own math. Mid-cycle upgrades are the common case, and hand-rolled proration is a bug factory.
- Seat-based plans sync the seat count to Stripe when memberships change, plus a rule for whether a removed seat credits now or at renewal.
- Trials belong in Stripe too, so trial-end and conversion arrive as events you already handle, not a cron job you forgot to write.
Gate features on the plan you read from your mirrored subscription record, refreshed by webhooks, never on a value the client sends. It is the same architecture we describe in our production stack, and the part clients most often ask us to fix after launch.
FAQ
What is the best multi-tenant architecture for a new SaaS?
For most B2B products, shared tables with a tenant ID on every row plus database-level row-level security. Reach for schema- or database-per-tenant only when compliance or a contract requires stronger isolation.
Should I build billing myself or use Stripe?
Use Stripe or a comparable provider and treat it as the source of truth. The value is not the payment form; it is the subscription lifecycle, proration, dunning, trials, and tax, that you do not want to reimplement or maintain yourself.
Where should user roles live in a multi-tenant app?
On the membership that links a user to an organization, not on the user record. That lets one person hold a different role in each account they belong to, which you will need the first time an agency or contractor signs up.
How long does it take to build this properly?
The tenancy, roles, and billing layer is usually a few weeks inside a larger build. Our SaaS MVPs typically run eight to twelve weeks end to end, with this plumbing wired in from the start rather than retrofitted.
Work with us
If you are building a SaaS and want the account, permission, and billing layer done right the first time, that is exactly the kind of web app development we do, a fixed quote after a short scoping call, and you own the code. Tell us what you are building on our contact page and we will give you an honest estimate.
