Building a multi-tenant application with Prisma
Tags: graphql, prisma, multitenancy
Published: 2019-08-28 15:57:24

## “Wait, what’s a multi-tenant application?”

Glad you asked, here is the [Wikipedia](https://en.wikipedia.org/wiki/Multitenancy) definition:

> _The term “**software multi-tenancy**” refers to a software architecture in which a single instance of software runs on a server and serves multiple tenants._

![Multi-tenancy](https://thepracticaldev.s3.amazonaws.com/i/fqhcine1vwbhg9qx21df.png)

**For example, Slack is a multi-tenant application, and [prisma.slack.com](https://prisma.slack.com) is one of its tenant.**

_“Alright, I get it. But why would I make a multi-tenant application?”_


Let’s make an analogy in which your application is a building, and each group of users is given an apartment. All these tenants are thus sharing the same walls, electricity and water network, waste treatment, etc.: you are mutualising the costs!

In our software world, it goes even further: As each “apartment” is made out of the same “plans” (i.e. the same piece of code), you can deploy your changes once, and they’ll be applied to every tenant!

_“Ok so multi-tenancy is a good way for me to reduce my costs in terms of infrastructure complexity and deployment time… That sounds interesting! How can I do that?”_

Well, you can use **[Prisma](https://prisma.io) services feature**. Follow the guide:

---

# Using Prisma for multi-tenancy

![Prisma](https://thepracticaldev.s3.amazonaws.com/i/bche5bz0kbjvei528u0i.jpeg)

For the rest of this article, I will assume you already know about Prisma and how it works. If you don’t, Prisma is a really awesome library **that replaces traditional ORMs**. I strongly suggest you [discover it](https://www.prisma.io/) and follow the [getting started tutorial](https://www.prisma.io/docs/get-started/01-setting-up-prisma-new-database-JAVASCRIPT-a002/).


## Prisma services

A Prisma service is defined by a **GraphQL datamodel** and a **name/stage** identification. Prisma servers can be configured to host multiple Prisma services.
Each Prisma service has exactly one endpoint, composed of the **server host**, **service name** and the **service stage**.

![Service endpoint](https://thepracticaldev.s3.amazonaws.com/i/h12ytzpi3ndf1j93e10d.png)

> _If you do not provide a service name or stage, they will be both assigned the value “default”._

To use Prisma services for a multi-tenant application, we can deploy **the same GraphQL datamodel to multiple services**.

## Starting our app with a single tenant

As an illustration, we’re going to take our previous example: Slack. Let’s then start with our datamodel and create an User and a Post:

```graphql
#datamodel.graphql

type User {
  id: ID!
  name: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
}
```

Then, deploy your datamodel to `https://localhost:4466/company_a/dev`.

We should now have a service ready for our application. Let’s write the server:

```js
// server.js

const { Prisma } = require('./generated/prisma-client')
const { ApolloServer } = require('apollo-server')
const resolvers = require('./resolvers')

const prisma = new Prisma({
  endpoint: 'https://localhost:4466/company_a/dev'
})

const server = new ApolloServer({
  resolvers: resolvers,
  context: ctx => ({
    ...ctx,
    prisma
  })
})

/*------------------------*/
/* In your resolvers file */
module.exports = {
  Query: {
    users: (_, args, ctx) => ctx.prisma.users(args)
  }
}
```

If you run your server, you should be able to query the users from the `company_a/dev` service. That’s a great start but as we’ve hardcoded our client’s service in our server, adding a new tenant wouldn’t be easy.

## Evolving into a multi-tenant app

In order to make our server multi-tenant, we will use the [prisma-multi-tenant](https://www.npmjs.com/package/prisma-multi-tenant) package.

[![prisma-multi-tenant](https://thepracticaldev.s3.amazonaws.com/i/m5l3gvc0ft4clvqp3ni3.png)](https://www.npmjs.com/package/prisma-multi-tenant)

```bash
npm install prisma-multi-tenant
```

Then, redeploy your datamodel to two more services:

- `https://localhost:4466/company_a/prod`
- `https://localhost:4466/company_b/dev`

Finally, we will change our server file to the following:

```js
// server.js

const { MultiTenant } = require('prisma-multi-tenant')
const { Prisma } = require('./generated/prisma-client')
const { ApolloServer } = require('apollo-server')
const resolvers = require('./resolvers')

const multiTenant = new MultiTenant({
  instanciate: (name, stage) =>
    new Prisma({
      endpoint: `https://localhost:4466/${name}/${stage}`,
      // Here, you are in charge of extracting the name/stage
      // of the service from the request.
      // As an example, we extract it from the headers
      nameStageFromReq: req => req.headers['prisma-service'].split('/')
    })
})

const server = new ApolloServer({
  resolvers: resolvers,
  context: ctx => ({
    ...ctx,
    prisma: multiTenant.current(ctx.req)
  })
})

/*------------------------*/
/* In your resolvers file */

// Did you notice we haven't touched our resolvers?
module.exports = {
  Query: {
    users: (_, args, ctx) => ctx.prisma.users(args) 
  }
}
```

As you can see, we created a `MultiTenant` object, and used its `current` method in the context option of ApolloServer. We also did not change our resolvers, as if we were still dealing with a single tenant.

> _For more details about [prisma-multi-tenant](https://www.npmjs.com/package/prisma-multi-tenant), check its [readme](https://www.npmjs.com/package/prisma-multi-tenant)._

Now, when you query your server, add the `prisma-service` HTTP header with the **name/stage** of the service you want to access (_“company_a/prod” for example_), and it will query the right service.

Aaand, that’s it. You’ve got a multi-tenant server.

_“Wait… That’s all we have to do? Using a library and querying with an HTTP header? Really?”_

We haven’t written a Slack-like application, but **yes, this is the foundation of your multi-tenant application**. Prisma is dealing with multiple database, and your server won’t care which. It will just work. Moreover, your server can now be deployed once, and handle requests coming from any tenants!

---

**I hope I’ve shown you why the Prisma services feature is the premium choice to easily build a multi-tenant application, with as little impact on your [developer experience](https://hackernoon.com/developer-experience-dx-devs-are-people-too-6590d6577afe) as possible.**

At [Zenika](https://github.com/zenika-open-source/FAQ), we built a production-ready multi-tenant application called FAQ to create an “Internal Knowledge Database for company collaborators” that helped reduce the recurrent email/slack questions about our internal processes. We had to overcome the challenges of working with multi-tenancy: simultaneous deployment (prisma and third-parties), developers tools, continuous integration of services…

If you are interested to know how we dealt with these issues, don’t hesitate to check the [github repository](https://github.com/zenika-open-source/FAQ) or contact me on [twitter](https://twitter.com/Errorname_)!