GenerateSaaS

Organizations

Add multi-tenant organizations with member roles, email invitations, owner and admin permissions, and billing scoped per user or per team.

Multi-tenancy is owned by @repo/auth via the Better Auth organization plugin and governed by config.tenancy. When multiTenant is true (the default), users create and join organizations; when false, the app is single-user and all team UI disappears.

Configuration

Everything is driven by config.tenancy:

// config.tenancy - the shipped default
tenancy: {
  multiTenant: true,         // teams on/off
  organizationLimit: 5,      // max orgs a user may create
  billingScope: "user",      // "user" | "organization"
}

config.tenancy is a discriminated union: { multiTenant: false } for single-tenant, or { multiTenant: true; organizationLimit?: number; billingScope } for teams.

KeyTypeDefaultDescription
multiTenantbooleantrueMaster switch. false = single-tenant, no org UI.
organizationLimitnumber5Max organizations one user can create (multi-tenant only).
billingScope"user" | "organization""user"Whether subscriptions attach to the user or the organization.

Read effective values via the @repo/config helpers, never config.tenancy directly: getBillingScope() and getOrganizationLimit() resolve the single-tenant fallbacks for you.

What multi-tenancy gives you

With multiTenant: true, the organization plugin adds:

  • Roles: every member is one of member, admin, or owner; the creator becomes owner.
  • Members: users belong to one or more orgs; the active org is tracked on the session, set to the most recently joined membership on login.
  • Invitations: owners/admins invite by email; the invitee opens /accept-invitation/{id} to accept and join with the assigned role.
  • Notifications: @repo/notifications fires on member joined, member removed, and role changed (not on the invite itself).
  • Audit: every invitation is recorded in the audit logs. The org activity feed reads those logs and is restricted to owner/admin.

Authorization rules (who can invite, remove, or change billing) are role-based - see Authorization.

Billing scope

billingScope decides who owns a subscription:

ValueDefault plan + credits seed ontoSeeded atUse when
"user"The individual user (default)User signupB2C / per-seat products
"organization"The organization, shared by all membersOrganization creationB2B / team plans

The hook seeds pricingConfig.defaultPlan and its credits onto the user (on signup) when scope is "user", or onto the org (when it is created) when "organization".

Set billingScope before going live. Switching it after customers subscribe re-points where new subscription records attach and can orphan existing ones.

Plans, checkout, and the customer portal read this scope automatically - see Plans and pricing.

When multiTenant is false

Setting config.tenancy = { multiTenant: false } hides all team surfaces:

  • No organization creation, switcher, members, or invitations UI; org-gated nav and admin pages disappear.
  • getOrganizationLimit() returns 1.
  • getBillingScope() forces "user" - subscriptions always attach to the user.
  • No schema changes needed; the organization tables simply go unused.

Frequently asked questions

Can a user belong to more than one organization? Yes. Membership is many-to-many; users switch the active org per session. organizationLimit only caps how many orgs each user can create, not join.

What happens to billing if I switch billingScope after launch? New subscriptions follow the new scope, but existing records stay where they were created. Change it before taking real payments to avoid orphaned subscriptions.

Who can invite or remove members? Role-based: owner and admin manage members and invitations; member cannot. The exact permission matrix lives in the authorization layer.

On this page