Multi-Tenancy Overview
Leave Localhost is designed as a B2B multi-tenant SaaS. It uses the concept of Organizations (often called Workspaces or Teams) to group users, data, and billing subscriptions.
Leave Localhost is designed as a B2B multi-tenant SaaS. It uses the concept of Organizations (often called Workspaces or Teams) to group users, data, and billing subscriptions.
Authentication and organization management are powered by Better Auth's Organization Plugin.
The Data Model
In the multi-tenant model:
- Users belong to one or more Organizations as Members.
- Data (records, settings, files) belongs to an Organization, not a User.
- Billing is tied to an Organization, not a User.
- A user acts on behalf of their Active Organization (workspace switcher).
Personal vs Team Mode
The starter can operate in two modes, controlled by
packages/backend/convex/organizations/config.ts:
Team Mode (Default)
- Users get a "Personal Workspace" on signup.
- Users can create new shared "Team Workspaces".
- Users can be invited to other workspaces.
- Best for B2B SaaS (Slack, Linear, Vercel).
Personal Mode
- Users get a single "Personal Workspace" on signup.
- Creation of additional workspaces is disabled.
- Invitations are disabled.
- Member management is disabled.
- Best for B2C SaaS or prosumer tools where users don't collaborate.
See Switching to Personal Mode for how to toggle this.
Organization Lifecycle
- Creation: When a user signs up, the
ensureDefaultOrganizationmutation automatically creates a Personal Workspace for them and sets it as active. - Team Creation: If team mode is on, users can create additional workspaces
via the
createWorkspacemutation. - Invitation: Users can invite others to join their workspaces via email.
- Deletion: Owners can delete an organization, which cascades to delete its data, subscriptions, and memberships.
The Active Organization
At any given time, a user is acting within their "Active Organization". This is stored in two places to keep the frontend and backend in sync:
- Better Auth Session:
session.activeOrganizationId - Convex User:
users.activeOrganizationId
The setActiveOrganization mutation safely switches the context, ensuring the
user is a valid member of the target organization.
Security and Scoping
All backend queries and mutations must filter data by the active organization.
The requireAppPermission helper makes this safe by returning the verified
organizationId:
const actor = await requireAppPermission(ctx, {
permission: "workspace.records.read",
});
const records = await ctx.db
.query("workspace_records")
// ALWAYS scope by the actor's organization
.withIndex("by_organizationId", (q) =>
q.eq("organizationId", actor.organizationId),
)
.collect();Next Reads
- Workspaces — workspace creation and switching.
- Members — member management.
- Invitations — the invitation flow.
- Roles and Permissions — role-based access.
- Capabilities — feature gating by plan.
- Workspace Demo — the built-in tenant data demo.
- Removing the Workspace Demo — remove the demo without removing organizations or workspace management.
Super Admin Access
Platform super admins can open the /admin panel. This is platform-scoped authorization, deliberately separate from organization/workspace roles: a workspace owner is not a platform admin.
Workspaces
"Workspace" is the UI term for an Organization. It represents the tenant boundary where data, billing, and members reside.