Prisma-multi-tenant uses a "management" datasource in order to keep track of all the tenants of your application.
Thanks to this management datasource, prisma-multi-tenant is able to migrate all your tenants at once, as well as providing you with a simple way to access the data of whichever tenant you want.
Prisma-multi-tenant is a two-part project:
- The CLI (
prisma-multi-tenant) that you will use to init, develop, and deploy your tenants - The Client (
@prisma-multi-tenant/client) that you will use in your app to access the data in your tenants
There are also plugins for Prisma-powered frameworks:
- The Blitz plugin (
@prisma-multi-tenant/blitz) which adds multi-tenancy to your Blitz application. - The Redwood plugin (
@prisma-multi-tenant/redwood) which adds multi-tenancy to your Redwood application.
Table of content:
Note: You can run the CLI with either
prisma-multi-tenantorpmt. Example:pmt init
Init multi-tenancy for your application
Options
| Name | Type | Description |
|---|---|---|
| url | String | URL of the management database |
| schema | String | Specify path of schema |
| no-example | Boolean | Disable creation of example file |
Examples
prisma-multi-tenant init
prisma-multi-tenant init --url=file:management.db
prisma-multi-tenant init --schema db/schema.prismaExplanations
The init command is used to initialize your application to use prisma-multi-tenant. It will do the following:
- Install
@prisma-multi-tenant/clientlocally in your app - Prompt for the management datasource url
- Update the
prisma/.envfile with the management's url - Generate PrismaClient (for tenants & management)
- Set up the management datasource
- Create first tenant based on the
DATABASE_URLenv variable - Create an example script (
multi-tenancy-example.js)
Note: Make sure you are using
DATABASE_URLin the default datasource of your schema.prisma file
List all tenants
Options
| Name | Type | Description |
|---|---|---|
| json | Boolean | Print using JSON Format |
Examples
prisma-multi-tenant list
prisma-multi-tenant list --jsonExplanations
The list command connects to the management datasource and returns all the tenants in it. You can use the --json argument to retrieve a machine-readable format of your tenants for any use case you want.
Create a new tenant or management
Arguments
| Name | Optional | Description |
|---|---|---|
| management | Yes | Create a new management |
Options
| Name | Type | Description |
|---|---|---|
| name | String | Name of the tenant |
| url | String | URL of the database |
| schema | String | Specify path of schema |
| no-management | Boolean | The new tenant will not be registered in the management database |
Examples
prisma-multi-tenant new
prisma-multi-tenant new --name=company_b --url=postgres://...
prisma-multi-tenant new --no-management
prisma-multi-tenant new managementExplanations
The new command create a new database using your schema. It will use a name, and an url (that you can provide as options).
If you want to create a tenant without tracking it in the management datasource, you can use --no-management. However be careful, because you will need to manually migrate up and down this tenant after that.
If you add the management argument, you can create a new management database. If you want to use this new management, don't forget to add the url in the prisma/.env file.
Use Studio to access a tenant
Arguments
| Name | Optional | Description |
|---|---|---|
| name | No | Name of the tenant you want to access |
Options
| Name | Type | Description |
|---|---|---|
| port | Number | Port to start Studio on |
| schema | String | Specify path of schema |
Examples
prisma-multi-tenant studio your_tenant_name
prisma-multi-tenant studio your_other_tenant --port=5556Explanations
The studio command will connect to the management datasource to retrieve the url of the tenant given as an argument. If you want to run multiple studios, you can pass a specific --port option.
Migrate up, down, or save tenants.
Note: You can also migrate up the management datasource to deploy another management database:
prisma-multi-tenant migrate management up -- --create-db
Arguments
| Name | Optional | Description |
|---|---|---|
| name | Yes | Name of the tenant you want to migrate |
| action | No | Migrate up, down, or save the tenant |
Options
| Name | Type | Description |
|---|---|---|
| schema | String | Specify path of schema |
Examples
prisma-multi-tenant migrate your_tenant_name down
prisma-multi-tenant migrate up
prisma-multi-tenant migrate save
prisma-multi-tenant migrate your_other_tenant up -- --auto-approve
prisma-multi-tenant migrate management up -- --create-dbExplanations
The migrate command is a wrapper to the @prisma/cli migrate command. If you pass the name argument, it will migrate a single tenant. Otherwise, it will apply the action to all of the tenants registered in the management datasource.
Any arguments written after -- will be passed to @prisma/cli migrate.
The save action will use the default DATABASE_URL value if no name argument is given.
Delete one tenant
Arguments
| Name | Optional | Description |
|---|---|---|
| name | No | Name of the tenant you want to delete |
Options
| Name | Type | Description |
|---|---|---|
| schema | String | Specify path of schema |
| force | Boolean | If true, will not ask for confirmation |
Examples
prisma-multi-tenant delete your_other_tenant
prisma-multi-tenant delete your_other_tenant --forceExplanations
The delete command will migrate down the tenant datasource and unregister it from the management datasource.
Generate Prisma Clients for the tenants and management
Options
| Name | Type | Description |
|---|---|---|
| schema | String | Specify path of schema |
| watch | Boolean | Watches the Prisma project file |
Examples
prisma-multi-tenant generate
prisma-multi-tenant generate --watchExplanations
The generate command generates the Prisma Client package for both Tenants and Management.
Set env variables for a specific tenant
Arguments
| Name | Optional | Description |
|---|---|---|
| name | No | Name of the tenant you want in your env |
Examples
prisma-multi-tenant env your_tenant_name -- npx @prisma/cli migrate save --experimentalExplanations
The env command uses management to add the URL of your tenant in the DATABASE_URL env variable. Because of that, you can use any @prisma/cli command you want and it will use the tenant you specified.
Eject prisma-multi-tenant from your application
Explanations
The eject command can be used if you no longer need prisma-multi-tenant in your application. This command will uninstall @prisma-multi-tenant/client. It will not touch your databases as you may have important data in them.
Displays the global help
Example
prisma-multi-tenant helpNote: The client will try to read the
MANAGEMENT_URLenvironment variables inprisma/.env, but you can also provide it yourself.
Constructor of the MultiTenant class.
Usage (JavaScript)
const { MultiTenant } = require('@prisma-multi-tenant/client')
const multiTenant = new MultiTenant()Usage (TypeScript)
This will give you autocompletion on your tenants
const { PrismaClient } = require('@prisma/client')
const { MultiTenant } = require('@prisma-multi-tenant/client')
const multiTenant = new MultiTenant<PrismaClient>()No management
If you do not want to connect to the Management database when connecting to a new Tenant, you can add the useManagement: false option:
const multiTenant = new MultiTenant({
useManagement: false,
})Returns the PrismaClient of your tenant. Any options passed as second argument will be given to the PrismaClient constructor.
If the tenant is present in the local cache, this method will return it. Otherwise, if the useManagement constructor's option is set to true, it will try to find the tenant in the management database.
If the tenant couldn't be accessed (either because useManagement: false or because it doesn't exist), this method will throw an error.
Usage
const prisma = await multiTenant.get('your_tenant_name')
const users = await prisma.users.findMany()
console.log(users)Returns the PrismaClient of your tenant. Any options passed as second argument will be given to the PrismaClient constructor.
This method does not connect to management.
Usage
const prisma = await multiTenant.directGet({
name: 'your_other_tenant',
url: 'file:something.db',
})
const users = await prisma.user.findMany()
console.log(users)Creates a new tenant in management and returns the corresponding PrismaClient. Any options passed as second argument will be given to the PrismaClient constructor.
This method will migrate up the new database to be up-to-date with the migrations.
Usage
const prisma = await multiTenant.createTenant({
name: 'a_new_tenant',
url: 'postgresql://the_postgres_url',
})
const users = await prisma.user.findMany()
console.log(users)Delete a tenant in management.
This method will migrate down the database.
Usage
await multiTenant.deleteTenant('my_tenant')Test if a tenant exists in management.
Usage
await multiTenant.existsTenant('my_tenant')Disconnects all PrismaClient instances (management & tenants)
Usage
await multiTenant.disconnect()Registers the middleware into Blitz. The tenantRouter function is required, and you can also provide prismaOptions to be passed to every Prisma Client instances used for the tenants.
Usage
In the blitz.config.js file:
const { multiTenantMiddleware } = require('@prisma-multi-tenant/blitz')
module.exports = {
// ...
middleware: [
multiTenantMiddleware((req, res) => {
// The name can come from anywhere (headers, token, ...)
return 'my_tenant_A'
}),
],
}Dynamically return the Prisma Client instance from the context. This replaces the generated code from Redwood.
Usage
In the api/src/lib/db.js file:
import { MultiTenant, fromContext } from '@prisma-multi-tenant/redwood'
export const multiTenant = new MultiTenant()
export const db = fromContext()Everywhere else:
import { db } from 'src/lib/db'
//
db.post.findMany()