Architecture12 min read

How to Build Multi-Tenant Authentication (Without Losing Your Mind)

LM
LoginMe Team
April 18, 2026

Most auth tutorials are written for a single-app world - one user table, one session, one login form. SaaS is not that world. SaaS is tenants: each customer gets their own slice, and that slice has to stay isolated from every other slice, even when the same person works at two of your customers.

Here is how multi-tenant authentication actually works, and the decisions you cannot undo once users exist.

Three Models for Multi-Tenancy

At the architecture level, you only have three options:

1. Database-per-tenant

Every tenant gets their own database. The cleanest isolation model; also the most expensive to operate. Use this when you have large enterprise customers who contractually require it, or strict data residency requirements. For a startup with small tenants, the operational overhead is usually not worth it.

2. Shared database, schema-per-tenant

One database, one schema per tenant. Compromise between isolation and operational cost. Common in mid-market B2B. Backups and migrations get interesting fast.

3. Shared database, tenant_id column

One database, one schema, every table has a tenant_id column. This is what most SaaS startups pick, and what you should pick unless you have a specific reason not to. Cheap, scales far, and lets you move to more isolation later if you need to.

Where the Pain Actually Is

The multi-tenant database model is not the hard part. The hard part is authentication identity. Specifically: is a user a "member of a tenant," or is a user a "global identity that happens to belong to tenants"?

Model A: Users belong to exactly one tenant

Simple to model. Works great until your first customer says "I also consult for this other company, can you give me access to both their dashboards with the same login?" Now you either say "no," build a second user row with a different password, or rewrite your auth model.

Model B: Users are global, memberships are per-tenant

A user identity exists once. The same identity can hold memberships in multiple tenants. Each membership has its own role, permissions, and optionally its own configuration. This is the model every grown-up SaaS converges on. Pick this one from day one.

The Join Table You Will End Up With

Regardless of which provider you use, the shape eventually looks like this:

user       (id, email, password_hash, ...)
tenant     (id, name, slug, ...)
membership (user_id, tenant_id, role, created_at, ...)

The membership table is where most of the real work happens. Invites point at it. Role checks read from it. Audit logs reference it.

Session Design

Here is a non-obvious decision: is a session global or tenant-scoped?

If a session is global, a user logs in once and can act across all their tenants without re-authenticating. Good UX, but you need to design every API call to include an explicit "acting as tenant X" parameter, and you need to make sure tokens do not leak privileges across tenants.

If a session is tenant-scoped, the JWT itself contains the current tenant_id. Switching tenants means re-issuing a token. Cleaner at the API boundary. Slightly worse UX.

The common compromise: one global session, and issue short-lived tenant-scoped access tokens on demand. That way every API call carries unambiguous tenant context, and users never feel like they are logging in twice.

Provisioning and Invites

Here is the invite flow every B2B SaaS needs, and almost none get right on the first try:

  1. Admin invites new@company.com to tenant T with role R.
  2. System generates a one-time invite token scoped to (email, tenant, role). Token has a clock on it.
  3. Email goes out with a deep link containing the invite token.
  4. Recipient clicks the link. Three branches:
    • Not logged in, account does not exist - registration flow, then accept.
    • Not logged in, account exists (different email) - sign in, then accept, with clear messaging about which email the invite was for.
    • Already logged in - accept immediately.
  5. Invite token is marked consumed. Membership row is created with role R.
  6. Audit log entry: invited_by, invited_at, accepted_at.

Miss any of these steps and you will have a long tail of "I can't find my invite" tickets.

Role Design: Four Roles, Not Forty

You want owner, admin, member, and optionally viewer. That is it. Every additional role is a cost you pay forever in permission checks and customer confusion. Add fine-grained permissions inside those roles later if you truly need them - usually you do not.

Audit Logs

Every action that affects another user, every login, every failed login, every role change, every token revocation. Write them to a dedicated, append-only store. SOC 2 auditors will ask for them. So will your first enterprise customer. So will you, when the "who deleted this" question comes up at 11pm.

The Verdict

Build multi-tenant authentication once, correctly, using the global-users + memberships model, with tenant-scoped tokens and a real audit log. Or use an auth provider that has already made these decisions correctly - and if you do, verify that its data model actually looks like the one above before you ship.

If you want to skip the design work and just get multi-tenant auth that already works this way, LoginMe gives you this model out of the box. Users, tenants, memberships, invites, roles, audit logs - all wired up, all accessible via API, fifteen minutes from signup.

Ready to get started?

Get started with LoginMe in 5 minutes - no credit card required