This is Part 2 of the series titled Deconstructing Data Models
{{line}}
Let’s consider the User and Workspace entities to understand application data models of B2B apps.
A user is any person who has signed up for an app (created an account), verified their email, and can start using the app – this is true for both B2C and B2B apps.
But unlike B2C apps that you’d typically use by yourself (in single-player mode), B2B apps enable you to collaborate with other users by inviting them to your account or workspace. In fact, when you sign up for a B2B app that is collaborative in nature (such as Notion or Slack), besides your user account, a workspace is also created automatically.
The user account and the workspace are distinct entities with distinct IDs, with a parent-child relationship between the workspace and the user. When an account is upgraded from free to paid, it is the workspace (parent) that’s upgraded. Even with multiple users in the workspace, the customer count goes up by exactly one. A user is not a customer unless we’re talking about single-player apps where the concept of a workspace is redundant (or optional).
One-to-Many
When designing the database schema for a B2B app, software engineers need to declare a parent-child relationship between the Workspace model and the User model where one workspace can have multiple users – a one-to-many workspace-user relationship.
The figure above depicts this relationship where users X and Y belong to the workspace A. As a result, each user’s identity is strictly tied to the workspace, as depicted by their respective user_id, AX and AY.
It’s useful to keep in mind that a one-to-many workspace-user relationship is the same as a many-to-one user-workspace relationship. While a workspace can have multiple users, each user in the workspace can only belong to that specific workspace.
If either X or Y is invited to join another workspace in the same app, they will have to create another user account that will have a different user_id. This application data model is typical of enterprise apps like Slack.
The figure below shows that the user Y has a separate user_id (AY and BY) for each of the two workspaces, A and B.
User and Workspace Models of Enterprise (only) Apps
Ever joined a Slack workspace using an email that you’ve used before, only to be treated as a new user? Slack asks you to enter your name and verify your email each time you join a new Slack workspace. You’re also able to use different names and different profile photos across multiple Slack workspaces that you’ve joined using the same email address.
Ever wondered why?
You see, the early engineers at Slack didn’t anticipate that it would be used to run communities, where a user joins multiple workspaces using the same email address; Slack was built to be used inside companies where one email address is only used to join one workspace. Therefore, Slack treats you as a distinct user in each workspace you join (or create) using the same email (even though Slack is able to identify you as one person).
This also explains why you can set up a unique password for each workspace you join using the same email or use existing credentials (email and password combination) to join a new workspace without being prompted that an account already exists using this email address.
Unlike those of prosumer apps we'll discuss below, the application data models of enterprise-only apps like Slack don’t need to account for a single-player experience.
The figure above is part of a conceptual schema for an enterprise app depicting the Workspace and User models with a one-to-many workspace-user relationship. As you can see, the workspace_id is the foreign key of the User model since a user can only belong to one workspace.
Many-to-Many
B2B apps like that allow a user to join or create multiple workspaces (without creating a new account using a different email), the workspace-user relationship is many-to-many. This application data model is typical of prosumer apps like Notion, Make, and Miro.
The figure above shows that user Y is part of both workspaces, A and B simultaneously, without the need to create a separate account. In a many-to-many model, a user’s identity isn’t tied to a specific workspace as the same user can join or create multiple workspaces.
You might be wondering why these apps are referred to as prosumer and how are they different from enterprise apps. Well, apps like Notion, Make, and Miro are referred to as prosumer since many of their customers are professionals or freelancers who use the respective apps in single-player mode, without the need to collaborate with others (I use all of them). That said, since these apps are also adopted by multiple teams at large enterprises, their application data models are fairly complex; let’s take a look.
User and Workspace Models of Prosumer Apps
Since individuals can use prosumer apps without necessarily collaborating with others, the application data models of these apps are designed differently as compared to standard B2B SaaS apps like Slack that can’t be used effectively (or at all) in single-player mode.
The key difference is this: When someone invites you via email to join their workspace on a prosumer app, you’re first asked to sign up or create your own account before you can join the account you were invited to. And if you already happen to have an account using that email, you’re asked to log in using your existing password.
The reason?
Besides using the app as part of the workspace you were invited to (which you can be removed from any time), the makers of prosumer apps also want you to use their apps by yourself – in single-player mode.
Therefore, you can be part of multiple Notion workspaces or Make organizations (another term for workspaces) using the same email address, without setting up a new password. The password bit is important because it signifies that the same user account is being attached to multiple workspaces, rather than a new user account being created for each workspace. This is not the case when someone invites you to join them on enterprise-only apps like Slack.
Therefore, apps that adopt the many-to-many workspace-user relationship enable gives every unique user their own workspace and a user is able to switch between the workspaces they own and the ones they’ve been invited to. We’ll discuss how this design choice impacts core metrics like active_accounts in a future guide but for now, let’s explore how it works.
The Role model
For B2B apps that adopt a many-to-many workspace-user relationship, besides User and Workspace, engineers need to declare another model that contains data about the role of a user in a workspace – the Role model (yup). Each user plays a distinct role in a workspace – such as Admin, Guest, Viewer, etc. – and can play different roles in different workspaces.
For instance, the same user can assume the role of an admin in account A and that of a guest in account B. Or a user might be given limited access to the product via a specific role, say, Manager that only allows them to view reports and make payments, rather than access the entire product.
Therefore, when a user creates or joins a workspace, a role is assigned to them either by the application itself or by the person who sends out the invite.
The figure above illustrates the following relationships between the User, Role, and Workspace models:
- Many-to-many user-role relationship: A user can assume multiple roles and a particular role, say, Manager, can belong to multiple users
- Many-to-many workspace-role relationship: A workspace contains multiple roles and a particular role, say, Admin, can be tied to multiple workspaces
The role model essentially enables a many-to-many users-workspace relationship, enabling a particular user to assume a distinct role in each workspace they belong to.
It’s worth noting that there are no foreign keys in the models shown in the figure above – the reason being that this figure is only illustrative. When there’s a many-to-many relationship between two entities, one needs to create what is known as a join table (or intermediate table). In the example above, the join tables can be called UserRole and WorkspaceRole and each table will contain the respective primary keys of the entities it joins. The technicalities of how these models are created in a database are beyond the scope of this book but you can check out this short article if you’d like to learn more.
Now back to the Role model. Besides enabling a many-to-many relationship between users and workspaces, it serves the following purposes:
- Software engineers use it to containerize access to parts of the app or personalize the user experience based on a user’s role in a workspace
- Data engineers leverage roles to create analytical data models for metrics such as avg_guest_seats_per_workspace to answer questions like “On average, how many guest seats are used by a workspace?”
- Growth practitioners use it to create better onboarding experiences and run better campaigns
For instance, during my Integromat days, the accountant role let assignees only view account and payment details (same on Make at the time of writing this). Did it then make sense to include accountants when calculating the number of active users?
Not really – not in Integromat’s case, at least.
In fact, we even excluded accountants from the standard onboarding process because their role prevented them from creating or editing scenarios. It would be silly to walk them through the process of doing something that they weren’t allowed to do in the first place, wouldn’t it? Similarly, users who were assigned the member role didn’t receive payment-related notifications because they didn’t have access to parts of the product that dealt with payments.
As mentioned earlier, a user could assume different roles across different workspaces and the role is what determines their experience, both inside and outside the app. However, the active_user_count metric would go up only by one even if a user was active in more than one organization.
This should help illustrate why it’s so important to think about the end-user experience when designing the application data models for a B2B app; user roles play a huge role in not only offering a coherent user experience but also reporting on metrics accurately.
It’s also useful to keep in mind that there’s no one-size-fits-all method and in fact, there are lots of creative ways to design the application data models in a manner that results in a good user experience and at the same time, makes things easy down the road for data and growth practitioners.
Lastly, the invitation flow of an app, for instance, can teach you a lot about how its application data models have been designed. Prosumer apps create a workspace for every unique user – something enterprise apps don’t. This is a key decision for software engineers at the time of building the app because such decisions can’t be undone without rebuilding parts of the app from scratch.
Additional Notes
The User model of a B2C app such as Spotify or Netflix is straightforward. A user pays for their own subscription that’s attached to the user account. But hey – Netflix allows multiple users to use the same account – you might say. Well, they only allow multiple screens to access an account at the same time using the same credentials (something B2B apps like Ahrefs don’t allow to prevent account sharing). And even though Netflix states that only people who live with you may use your account, there’s no equivalent of a workspace – like a household – where you invite others to join your household using their email. In fact, Netflix doesn’t even know who has logged in to your account, which explains the prompt “Who’s watching?”
Spotify, on the other hand, now offers Duo and Family plans that come with multiple user accounts with centralized billing, allowing the plan owner to invite others to create a user account under the same plan. This model brings Spotify’s data model a little closer to that of a prosumer app since a user can choose to pay for a single user account or purchase the Duo or Family plans that mimic B2B workspaces.
In part 3, we'll dig into the fundamentals of Analytical Data Models.