16 Multi-Tenancy

Multi-Tenancy, as it relates to software development, is when a single instance of an application is used to service multiple clients (tenants) in a way that each tenant’s data is isolated from the other.

To use the Micronaut’s multitenancy capabilities you must have the multitenancy dependency on your classpath.

  1. implementation("io.micronaut:micronaut-multitenancy")
  1. <dependency>
  2. <groupId>io.micronaut</groupId>
  3. <artifactId>micronaut-multitenancy</artifactId>
  4. </dependency>

A common requirement for supporting Multi-tenancy is the ability to resolve the current tenant. Micronaut ships with the following built-in TenantResolvers:

name

description

CookieTenantResolver

Resolves the current tenant from an HTTP cookie. See CookieTenantResolver Configuration Properties.

FixedTenantResolver

Resolves against a fixed tenant id. See FixTenantResolver Configuration Properties.

HttpHeaderTenantResolver

Resolves the current tenant from the request HTTP Header. See FixTenantResolver Configuration Properties.

PrincipalTenantResolver

Resolves the current tenant from the authenticated username. See PrincipalTenantResolver Configuration Properties.

SessionTenantResolver

Resolves the current tenant from the HTTP session. See SessionTenantResolver Configuration Properties.

SubdomainTenantResolver

Resolves the tenant id from the subdomain. See SubdomainTenantResolver Configuration Properties.

SystemPropertyTenantResolver

Resolves the tenant id from a system property. See SystemPropertyTenantResolver Configuration Properties.

Micronaut supports tenant propagation. As an example, take the following scenario:

multitenancy

You want incoming requests to the gateway microservice to resolve the tenant id via subdomain. However, you want your requests to other internal microservices to include the tenant Id as an HTTP Header.

Your configuration in the gateway microservice will look like:

  1. micronaut:
  2. multitenancy:
  3. propagation:
  4. enabled: true
  5. service-id-regex: 'catalogue'
  6. tenantresolver:
  7. subdomain:
  8. enabled: true
  9. tenantwriter:
  10. httpheader:
  11. enabled: true

In the catalogue microservice the configuration will look like:

  1. micronaut:
  2. multitenancy:
  3. tenantresolver:
  4. httpheader:
  5. enabled: true

To propagate the tenant you will need to write the resolved tenant ID to the outgoing requests.

Currently, Micronaut ships with two built-in implementations for TenantWriter:

name

description

CookieTenantWriter

Writes the current tenant to a Cookie in your outgoing requests. See CookieTenantWriter Configuration Properties.

HttpHeaderTenantWriter

Writes the current tenant to a HTTP Header. See HttpHeaderTenantWriter Configuration Properties.

16.1 Multi-Tenancy GORM

GORM supports Multi-tenancy and integrates with Micronaut.

To use Micronaut and GORM multitenancy capabilities you must have the multitenancy-gorm dependency on your classpath. For example in build.gradle:

build.gradle

  1. compile "io.micronaut.configuration:micronaut-multitenancy-gorm"

GORM is a powerful Groovy-based data access toolkit for the JVM with implementations several data access technologies (Hibernate, Neo4j, MongoDB, GraphQL …​).

GORM supports the following different multitenancy modes:

  • DATABASE - A separate database with a separate connection pool is used to store each tenants data.

  • SCHEMA - The same database, but different schemas are used to store each tenants data.

  • DISCRIMINATOR - The same database is used with a discriminator used to partition and isolate data.

In order to use GORM - Multitenancy you will need to configure the following properties: grails.gorm.multiTenancy.mode and grails.gorm.multiTenancy.tenantResolverClass.

Micronaut support for Multi-tenancy integrates with GORM.

The following table contains all of the TenantResolver implementations that ship with `multitenancy-gorm module and are usable out of the box.

name

description

CookieTenantResolver

Resolves the current tenant from an HTTP cookie.

FixedTenantResolver

Resolves against a fixed tenant id

HttpHeaderTenantResolver

Resolves the current tenant from the request HTTP Header.

PrincipalTenantResolver

Resolves the current tenant from the authenticated username.

SessionTenantResolver

Resolves the current tenant from the HTTP session.

SubdomainTenantResolver

Resolves the tenant id from the subdomain.

SystemPropertyTenantResolver

Resolves the tenant id from a system property.

You will need to add something like the following snippet to your app configuration:

  1. grails:
  2. gorm:
  3. multiTenancy:
  4. mode: DISCRIMINATOR
  5. tenantResolverClass: 'io.micronaut.multitenancy.gorm.PrincipalTenantResolver'

Please, read GORM Multi-tenancy documentation to learn more.