Boilerplate-Stack
Back to blog
Articles

Multi-Tenant Architecture for SaaS: From Solo Users to Enterprise Teams

|
3 min read

What Is Multi-Tenancy Exactly?

Multi-tenancy is the ability of software to serve multiple clients (tenants) from a single instance. In a SaaS, each tenant is typically an organization, a team, or an individual account. The challenge is isolating each tenant's data while sharing infrastructure to reduce costs.

This is a fundamental topic for any serious SaaS, yet most boilerplates ignore it or handle it superficially. Boilerplate-Stack offers a complete and proven multi-tenancy implementation.

The Three Models of Multi-Tenancy

1. Separate Database per Tenant

Each client has their own database. Maximum isolation, but enormous operational complexity: migrations, backups, multiple connections.

  • Advantage: total data isolation
  • Disadvantage: exponential cost and management complexity
  • Suited for: enterprises with strict regulatory constraints

2. Separate Schema per Tenant

A single database but a PostgreSQL schema per tenant. Better compromise but migrations become complex since they must be applied to each schema.

  • Advantage: good isolation, same infrastructure
  • Disadvantage: N-time migrations, complex connection pooling
  • Suited for: B2B SaaS with dozens of large clients

3. Shared Database with Row Level Security (RLS)

All tenants share the same tables. Isolation is enforced by PostgreSQL-level RLS policies. This is the most efficient and scalable model.

  • Advantage: simplicity, performance, scalability
  • Disadvantage: requires rigorous RLS implementation
  • Suited for: 99% of SaaS products

This third model is what Boilerplate-Stack implements, using Supabase and PostgreSQL.

The Account-Centric Architecture

The core of multi-tenancy in Boilerplate-Stack is the account-centric model:

USER (auth.users)
    │
    │ can have multiple
    ▼
MEMBERSHIPS (user_id, account_id, role_slug)
    │
    │ belongs to
    ▼
ACCOUNT (type: personal | workspace)
    ├── credits_balance
    ├── Subscriptions
    ├── Chat Sessions
    ├── AI Requests
    └── API Keys

Personal Accounts vs Workspaces

  • Personal: auto-created on signup. 1 user = 1 personal account. Ideal for B2C.
  • Workspace: manually created or after checkout. N users = 1 workspace. Invitations, roles, team management.

The businessModel configuration in config/app.ts determines the mode:

  • 'b2c': personal accounts only
  • 'b2b': workspaces enabled with invitations and team management

Row Level Security in Practice

Every table containing tenant data has an account_id column and an RLS policy:

CREATE POLICY "members_access" ON chat_sessions FOR SELECT
USING (EXISTS (
  SELECT 1 FROM memberships
  WHERE memberships.account_id = chat_sessions.account_id
  AND memberships.user_id = auth.uid()
));

This pattern ensures a user can only access data from accounts they are a member of. The check happens at the PostgreSQL level, not the application level.

Dynamic Roles System

Roles are not hardcoded. They are stored in a roles table with JSONB permissions:

-- Example role
{
  "slug": "admin",
  "permissions": {
    "manage_members": true,
    "view_billing": true,
    "manage_billing": false,
    "delete_workspace": false
  },
  "is_system": true
}

The hierarchy is: owner > admin > member > custom roles. System roles are protected from deletion. Administrators can create custom roles from the dashboard.

Invitations and Team Onboarding

The invitation flow in Boilerplate-Stack:

  1. Admin invites by email with an assigned role
  2. An invitation token is generated (7-day expiry)
  3. The invitee receives an email with a unique link
  4. Acceptance: membership is created with the role
  5. If the invitee does not have an account, one is created automatically

Account Switcher

When a user belongs to multiple accounts (personal + workspaces), an Account Switcher component allows switching between contexts. All displayed data (credits, sessions, members) changes based on the active account.

Go Multi-Tenant Without the Effort

Implementing multi-tenancy correctly is one of the most complex challenges in a SaaS. RLS, roles, invitations, account switching — every piece must fit together perfectly.

Boilerplate-Stack provides all of this out of the box, tested and documented. Focus on your product, not on multi-tenant plumbing.