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 KeysPersonal 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:
- Admin invites by email with an assigned role
- An invitation token is generated (7-day expiry)
- The invitee receives an email with a unique link
- Acceptance: membership is created with the role
- 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.