These are notes based on the article: Ultimate guide to multi-tenant SaaS data modeling
The top most level is organization (since it is naming, it can be called other things but will be referred to as organization in this case - which also makes sense for users).
Three models
- GitHub: Each person has one account that can belong to one or more organizations
- Google: Each person has a unique account for each organization
- Linear: Each person can have one or more accounts and each account can belong to one or more organizations
Data modeling:
- Every table except the
userstable should haveorganization_idwhich is a foreign key reference to theorganizationtable - The mapping table between the
userstable and theorganizationtable is theMembershiptable - Since every table will be first queries on
organization_id, create an index on this column - (Optional) Make the primary key for each table a combination of
organization_idandtable_id(organization_id, table_id). This will help if we want to clone an organization’s data into a sandbox environment for testing. - Assign items to the user’s membership instead of the user directly.
- Require
organization_ideverywhere - in the URLs (ex:/org/[orgId]/projects/[projectId]), query inputs, database calls, etc.
User login sessions
Three implementations with varying degrees of complexity and challenges it solves.
- Basic
- Store
organization_idin the session - Assuming a user has access to org1 and org2 and they are only logged into org1, if they try to access org2, they will not be able to access org2
- Store
- Mid
- Store all the organization a user has access to along with the role for each organization in the user session:
accessibleOrgs: Array<{orgId: string, role: string}> - If a user is revoked or their role changes, update all the user’s sessions
- The problem with this implementation is that one of the orgs the user belongs to might require a particular way of auth (ex: Google or SSO). In this case, we cannot automatically allow access to the user for this auth when they logged in using, say, email/password
- Store all the organization a user has access to along with the role for each organization in the user session:
- Ultimate
- Store two things in the user session:
accessibleOrgs: Array<{orgId: string, role: string}>- synced across all user sessionsloggedInOrgsOnThisDevice: Array<{orgId: string}>- not synced across all user sessions
- Set
accessibleOrganizationsto the list of all their org memberships - Set
loggedInOrgsOnThisDeviceto the same asaccessibleOrganizationsbut filtered by orgs that permit access with the login method (like email/password vs Google) - User will log into other orgs by clicking on the “Sign into organization” from the org switcher
- Once they sign in using the other org’s preferred scheme, add the new org id to
accessibleOrganizations, if it’s not already there, and tologgedInOrgsOnThisDevice
- Store two things in the user session:
User sign up flow
- Direct signup
- Create
organizationandmembership - Create
user - Add
usertomembership
- Create
- Invitation
- Create
membershiprecord withinvitationId,invitationExpiresAt, andinvitedEmail membership.userIdwill benull- Create a link with the
invitationId - When user signs up, check if the
invitationIdmatches themembershipto create theuserand attach it to themembership
- Create
Role-based access controls
- Store the
rolein user session to avoid API calls - Maintain a list of permissions for each role
- Check if user has access to perform the query or mutation based on the role
Billing
- Store the billing information at
organizationlevel (ex:billingEmail,stripeCustomerId, etc) - An
organizationcan have multiplesubscriptions - For usage based billing, calculate the count of items that belong to that
organization
Settings
Three types of settings:
- Organization settings - Store it on the
organizationtable - User settings at org level (ex: notifications) - Store it on the
membershiptable - User settings at global level (ex: dark mode) - Store it on the
usertable
This post is basically notes from reading the Ultimate guide to multi-tenant SaaS data modeling article.
The article further references: