Multi-tenant application. What is it and why does it matter?
A multi-tenant application is an application that support multiple tenants, usually customers, where each customer has an isolated environment in your system.
If you are building a SaaS app you must likely are building a multi-tenant application where each of your customer has its own login and can access its own data. But you share resources such as frontend, backend and database to keep costs low, maintenance easy and development fast.
So let's see how we could do this with Nhost and Hasura
We will build a Customer Relationship Management (CRM).
In the Nhost console, create a new project.
The Hasura instance and database comes ready with users table. We track all tables and relationships. Next we manually create two more tables for our CRM.
companies
tableThe companies are each tenant in the CRM and each company are a customer to us.
customers
tableNext we'll add a foreign key to the users table. The customers.user_id
is going
to reference the user who is responsible for the customer. Note the we set the On
Delete Violation to set null. So if the user thats responsible for the customer
gets deleted, the value of customers.user_id will automatically be set to null.
Last thing before adding this customers table is to set a unique constraint on the email column. This will make sure we won't have any duplicated customers with the same email.
To at least add a little bit of functionality in our simplistic CRM we add the functionality to add and manage comments for every customer. So each company can make internal notes for each customer.
Now we have our tables set up. Next we will add the column company_id to our users table so that every user is part of a company. We'll also create a foreign key between the users and the companies tables.
Our tables are setup correctly and it's time to set up some example data. First, we will add
Let's add two test users for two different companies. We'll add the users in the Nhost console.
Next, let's add the two companies in the companies table in the database.
Next, let's take the id of the respective companies and update the users company_id field.
Then we will activate the column company_id as a permission variable (session variable) for Hasura to be able to use the company_id in Hasuras permission system. We check the
company_id` in the Hasura console under Settings -> Authentication -> Edit.
Next, let's track all relationships in Hasura. This enables Hasura to follow all foreign keys and create the relationships for the GraphQL API. Klick Track All next to Untracked foreign-key relations.
Time to create the permissions to make sure users are only allowed to insert/select/update/delete correctly. We'll start with the insert in the customers
table.
When a user inserts a new customer we want that new customer to have the correct fields for user_id
and company_id
so a user from ex company Nike only can insert customer that's associated to company Nike. Also we want the customer to be connected to the user.
We do this by Column presets. Column presets will automatically populate a column in the database with a value from a session variable. This makes sure the value is correct and can not be tampered with by any users.
So we set user_id
to get the value in the session variable x-hasura-user-id
and company_id
to get the value in the session variable x-hasura-company-id
.
We also only enable a user to insert values for email
and name
becuase all other values gets set automatically.
For select we only want users to be able to select customers that has the same company_id
as the x-hasura-company-id
session variable as the user. So we make the following check for selecting customers:
{
"company_id": {
"_eq": "X-Hasura-company-id"
}
}
Ok, so we have made our tables and we have created some permissions. Time to test our backend. Let's go back to the Hasura console and to the GraphQL API tab. Here we can select a specific user to make the request from. We select the user in the select input in the top left corner. We insert one customer with Alice at Nike and another user with Bob at Coca-Cola.
We now have two customers in the database. One customer for each company.
Back in our GraphQL API, we make a request to get all customers as alice@nike.io. As you see, we only get the one customer associated with the company which Alice is part of.
Same thing if we switch user to bob@cocacola.com and make the exact same query.
In this blog post we have showed you how you can model your multi tenant application with Nhost and Hasura. This is done by using the session variables for a user and make the appropriate permission rules with custom permission checks and column presets.
The Jamstack backend with Hasura.