Multi-tenancy guide
Today we're diving into a complex, yet essential, topic: utilizing Meilisearch in a multi-tenant application. By the end of this guide, advanced and intermediate developers will have a clear understanding of how to configure Meilisearch to manage multi-tenancy effectively.
Multi-tenancy: what is it?
In a multi-tenant architecture, a single instance of a software application serves multiple customers or "tenants". Each tenant's data is isolated and remains invisible to other tenants.
Multi-tenancy use cases
A typical use case for multi-tenancy is in Software as a Service (SaaS) applications, where multiple companies share the same database. Each company becomes a tenant with data that should not be accessible by others. In such scenarios, you're likely already implementing this specificity in your primary data store.
Multi-tenancy with Meilisearch: the ultimate approach
While it's possible to create one index per company with Meilisearch, it's not recommended due to performance reasons. Meilisearch processes tasks one index after another and cannot maximize the indexation throughput, as cannot process tasks on different indexes in parallel.
Instead, the best way is to put all tenants in the same index and use Meilisearch's powerful tenant tokens to restrict access to a specific user's scope only. For this, stored documents should have not only an ID but also a company identifier to separate users by their company.
Preparing Meilisearch for multi-tenancy
Let's illustrate this with an example akin to a Slack application. In this application, users belong to a company, and each user can create text messages in different threads. Our goal is to create an index containing all messages but allow only people from a specific company to access their company's messages. Subsequently, we might want to perform a search applying filters on users and threads.
First, we need to transform our data to make it optimal for indexing by Meilisearch. Here's what a sample document could look like:
{
"id": 48735873,
"user":{
"id": 5749,
"name": "bob"
},
"company": {
"id": 838,
"name": "Acme Inc"
},
"thread": "meilisearch-is-awesome",
"data": "Meilisearch is so easy to use! 🔥",
"created_at": 1543230000
}
Next, you'll need to create a messages index and add the following settings:
{
"displayedAttributes": [
"id",
"user.name",
"thread",
"data",
"created_at"
],
"searchableAttributes": [
"data"
],
"filterableAttributes": [
"user.name",
"company.id",
"thread"
],
"sortableAttributes": [
"created_at"
]
}
Here's what each setting does:
displayedAttributes
: These are the attributes that will appear in your application's search results. We're omittinguser.id
andcompany.id
for security reasons, andcompany.name
isn't necessary as the user is already aware of their company.searchableAttributes
: These are the attributes that the search function will use. In our case, only thedata
(or message text) is searchable.filterableAttributes
: These are the attributes that you can filter by. We've includedcompany.id
for the tenant tokens,user.name
, andthread
for on-the-fly filtering.sortableAttributes
: These are the attributes you can sort by. We've only includedcreated_at
as you might want to sort messages chronologically.
Creating tenant tokens
With your Meilisearch configuration in place, the next step is to create a new tenant token for each company. If you don't have particular security concerns, you can omit the expiration date to simplify your onboarding process.
The crucial part of the tenant tokens is the searchRules
. In our example, you'll add the following rule:
{
"messages": {
"filter": "company.id = 838"
}
}
With the generated token, your search will restrict access based on company.id
, so users will only see messages within their company.
Store this token in your primary data store (Postgres, MySQL, etc.). This mechanism is similar to those used in tools like Stripe.
Each time a user logs into your app, load this key into local storage and use it for the searches, ensuring that each user only has access to data relevant to their company.
Conclusion
Creating a multi-tenant application using Meilisearch is quite straightforward once you understand how to structure your data and configure your search attributes correctly. By following this guide, you can ensure that your application provides a secure, efficient, and user-friendly search experience. If you have any question, you can join us on Discord.
Boost productivity and streamline development with Meilisearch Cloud. No more server deployment or manual updates. Try it free for 14 days, no credit card needed.
For more things Meilisearch, subscribe to our newsletter. You can learn more about our product by checking out our roadmap and participating in our product discussions.
Happy coding!