Skip to content
Search

    Multitenancy

    Introducing the fundamental concepts of multitenancy, underpinning SaaS solutions in CAP. It describes how to run and test apps in multitenancy mode with minimized setup and overhead.

    Introduction & Overview

    CAP has built-in support for multitenancy with the @sap/cds-mtxs package.

    Essentially, multitenancy is the ability to serve multiple tenants through single clusters of micro service instances, while ensuring strict isolation with respect to tenants’ data and access to it. Tenants are clients using SaaS solutions.

    In contrast to single-tenant mode, applications aren’t serving end-user request immediately after deployment, but wait for tenants to subscribe.

    Enable Multitenancy

    Add @sap/cds-mtxs Package Dependency

    npm add @sap/cds-mtxs
    

    Switch on cds.requires.multitenancy

    Add the following configuration, for example, to your package.json:

      "cds": {
        "requires": {
          "multitenancy": true
        }
      }
    

    In essence, this configuration option tells the CAP Node.js runtime to run in multitenancy mode. In particular, this means using tenant-specific database connection pools.

    Test-Drive Locally

    In order to test multitenancy, just run your CAP server as usual, then log on with different users, assigned to different tenants, to see the effects.

    Start Server with cds watch as Usual

    cds watch
    

    This produces an output like that:

    image-20220704173230030

    In contrast to single-tenant mode, we recognize differences in the log output with regards to the database initialization and the services that are bootstrapped.

    Deferred Database Initialization

    Tenant-specific databases are initialized on tenant subscriptions only.

    We can recognize that from the log output. The in-memory database init messages are missing, which would show up in single-tenant mode:

    image-20220705061944399

    MTX Services Bootstrapped

    These MTX services are served in addition to our application services:

    • cds.xt.ModelProviderService
    • cds.xt.DeploymentService
    • cds.xt.SaasProvisioningService

    Learn more about these services in MTX Services Reference

    In essence, the started server is now waiting for tenant subscriptions. Note: No end-user requests can be served yet.

    Subscribing Tenants

    Upon tenant subscriptions required tenant-specific resources need to be created and initialized, most prominently the tenants’ databases.

    Send subscribe Events

    Now, let’s subscribe tenants by sending subscribe events to the DeploymentService using any REST Client plugin in VSCode:

    POST http://localhost:4004/-/cds/deployment/subscribe HTTP/1.1
    Content-Type: application/json
    Authorization: Basic yves:
    
    { "tenant": "t1" }
    

    For example, send two such requests to subscribe tenants t1 and t2:

    Bootstrapping Tenant-Specific Databases

    In response to each subscribe request, the server deploys and bootstraps a new isolated in-memory database for each, tenant t1, and tenant t2, which can be seen from respective log outputs:

    image-20220704173514145

    Upgrading Tenants

    Later on when our app is enhanced, we can upgrade subscribed tenants. Use the upgrade request that is very similar to the subscribe requests before.

    Send upgrade Events

    POST http://localhost:4004/-/cds/deployment/upgrade HTTP/1.1
    Content-Type: application/json
    Authorization: Basic yves:
    
    { "tenant": "t1" }
    

    In response to upgrade request, the DeploymentService reads the latest models and content from the latest deployed version of the application and redeploys that to the respective tenant’s database.

    Serving Tenants

    Now, as we have our tenant-specific databases deployed and filled, our server can serve tenant-specific end-user requests. In our nutshell setup we can demonstrate this as follows:

    Use the App with Different Users/Tenants

    1. Open a new anonymous browser window.
    2. Open http://localhost:4004/vue/index.html in it.
    3. Log in as carol.
      — a pre-defined user in tenant t1 in the built-in mocked auth strategy image-20220704175231254
    4. List of Books is displayed with user + tenant information at the top. image-20220704181229423

    Repeat these steps, this time login in with erin another pre-defined user in tenant t2.

    Tenant Isolation

    As we can see also from the server’s log output, in multitenant mode, all end-user requests happen within the context of a specific tenant, which the individual users are assigned to:

    image-20220704175430969

    The CAP runtimes guarantee, that each request is served in isolation, which means all work on separate app data, both in service layers as well as in databases.

    You can validate this, for example by ordering a few books in the carol window, then ordering some other books in the erin window and see that both have independent data.

    Authentication and Tenants

    How users are assigned to tenants and how tenants are determined at runtime largely depends on your identity providers and authentication strategies. The mocked authentication strategy, used by default with cds watch, has some pre-defined users configured via cds env defaults. You can inspect these by running cds env get requires.auth :

    image-20220704180436619

    You can also add or override users or tenants by adding something like this to your package.json:

    "cds":{
      "requires": {
        "auth": {
          "users": {
            "u2": { "tenant": "t2" },
            "u3": { "tenant": "t3" }
          }
        }
      }
    }
    

    MTX Services Reference

    See Reference docs for MTX Services to learn more about the detailed service and configuration options, in particular also about setting up MTX sidecars.

    Old MTX Reference

    See Reference docs for former, ‘old’ MTX Services.