Skip to Content
Technical Articles
Author's profile photo Prabhanjan Kumar

Multitenant application using Cloud Application Programming Model (CAP)

This example demonstrates how to build multitenant application using Cloud Application Programming Model Java SDK and mtx-sidecar node module.


This sample application contains

  • UI module containing a public welcome page which contains link to fetch data from its own tenant database.
  • backend module which contains CDS service exposing OData CRUD APIs on Books entity
  • Database (db) module which contains schema.cds to create books table
  • Node.js based mtx-sidecar module used to handle tenant provisioning

What is Multitenancy?

SAP BTP provides a multitenant functionality that allows application providers to own, deploy, and operate tenant-aware applications for multiple consumers, with reduced costs.

With tenant-aware applications, you can:

  1. Separate data securely for each tenant
  2. Save resources by sharing them among tenants
  3. Update applications efficiently in a single step

Configuring the Approuter, required services and mtx-sidecar module:

To enable multitenancy on the SAP BTP, we need to deploy tenant aware approuter, mtx-sidecar module and configure below three services.

Only when these services are bound to your application, the multitenancy feature is turned on.

  1. XSUAA
  2. Service Manager
  3. SaaS Provisioning service (saas-registry)

Approuter module:

You deploy the approuter application as a Cloud Foundry application and as a logical part of the multitenant application. Then you configure approuter application as an external access point of the application.

Each multitenant application has to deploy its own application router and the application router handles requests of all tenants to the application.

The application router must determine the tenant-specific subdomain. This determination is done by using a regular expression defined in the environment variable TENANT_HOST_PATTERN. The application router then forwards the authentication request to the tenant User Account and Authentication (UAA) service and the related identity zone.

If you have multiple routes to the same application, for example:

tenant1.<application domain> and tenant2.<application domain>


TENANT_HOST_PATTERN: "^(.*)-<application domain>"




Bind your multitenant application and the approuter application to the SAP Authorization and Trust Management service (technical name: xsuaa) instance, which acts as an OAuth 2.0 client to your application.

In multi-tenant environments, tenants subscribe to and consume applications, which are registered as clients at the XS UAA. XS UAA creates a new OAuth2 client per application for each tenant. The shared tenant mode is mandatory for an application router configured for multi-tenancy applications. Also, a special configuration of an XS UAA service instance is required to enable authorization between the SaaS Provisioning service, Cloud Application Programming Model Java application, and MTX sidecar.

The service can be configured in the mta.yaml by adding an xsuaa resource as follows:

-  name: <xsuaa instance name>
      service-plan: broker
      path: ./security.json
         xsappname: <appname>

Choose a value for property xsappname that is unique globally.

An example security.json file looks like this:

    "xsappname": <appname>,
    "tenant-mode": "shared",
    "scopes": [
            "name": "$XSAPPNAME.mtcallback",
            "description": "Multi Tenancy Callback Access",
            "grant-as-authority-to-apps": [
                "$XSAPPNAME(application, sap-provisioning, tenant-onboarding)"
            "name": "$XSAPPNAME.mtdeployment",
            "description": "Scope to trigger a re-deployment of the database artifacts"
    "authorities": [

The mtcallback scope is required by the onboarding process. The mtdeployment scope is required to redeploy database artifacts at runtime.

Service Manager:

A service-manager instance is required that the Cloud Application Programming Model Java SDK can create database containers per tenant at application runtime. It doesn’t require special parameters and can be added as a resource in mta.yaml as follows:

-  name: service-manager
   type: org.cloudfoundry.managed-service
      service: service-manager
      service-plan: container

SaaS Provisioning Service (saas-registry):

A saas-registry service instance is required to make your application known to the SAP BTP Provisioning service and to register the endpoints that should be called when tenants are added or removed. The service can be configured as a resource in mta.yaml as follows

- name: saas-registry
  type: org.cloudfoundry.managed-service
    service: saas-registry
    service-plan: application
        appName: <app display name> # this is the text on the tile
        xsappname: <appname> # this is the value from xsuaa.parameters.config.xsappname
          getDependencies: ~{srv/url}/mt/v1.0/subscriptions/dependencies
          onSubscription: ~{srv/url}/mt/v1.0/subscriptions/tenants/{tenantId}
    - name: srv
  • appName: Choose an appropriate application display name.
  • xsappname: Use the value for xsappname you configured at your UAA service instance.
  • appUrls: Configure the callback URLs used by the SaaS Provisioning service to get the dependencies of the application and to trigger a subscription. In the above example, the property ~{srv/url} that is provided by the srv module is used.

mtx-sidecar module:

Cloud Application Programming Model provides the npm module for Node.js published as @sap/cds-mtx on It provides APIs for implementing SaaS applications on SAP BTP. Java applications need to run and maintain the cds-mtx module as a sidecar application. Multitenant Cloud Application Programming Model Java applications automatically expose the tenant provisioning APIs.

provisioning: implements the subscription callback API as required by SAP BTP. If a tenant is subscribing to the SaaS application, the onboarding request is handled. cds-mtx is contacting the SAP HANA Service Manager service to create a new HDI container for the tenant. Then, database artifacts get deployed into this HDI container. In addition, the unsubscribe operation and the “get dependencies” operations are supported.

This section describes how to use the cds-mtx Node.js module and add the MTX sidecar microservice to the mta.yaml file.

In a dedicated project subfolder named mtx-sidecar, create a Node.js start script in a file named server.js to bootstrap the cds-mtx library:

const app = require('express')();
const cds = require('@sap/cds');

const main = async () => {
	const PORT = process.env.PORT || 4004;
	const scope = process.env.CDS_MULTITENANCY_SECURITY_SUBSCRIPTIONSCOPE || 'mtcallback';

	const provisioning = await'ProvisioningService');
	provisioning.before(['UPDATE', 'DELETE', 'READ'], 'tenant', async (req) => {
		// Check for the scope of the SaaS Provisioning Service
		if (! {
			// Reject request
			const e = new Error('Forbidden');
			e.code = 403;
			return req.reject(e);



To define the dependencies and start command, also create a file package.json like this:

    "name": "deploy",
    "dependencies": {
        "@sap/cds": "^5.0.4",
        "@sap/cds-mtx": "^1.2.0",
        "@sap/hdi-deploy": "^4.0.4",
        "@sap/instance-manager": "^2.2.0",
        "@sap/xssec": "^3",
        "@sap/hana-client": "^2.8.16",
        "express": "^4.17.1",
        "passport": "^0.4.1"
    "scripts": {
        "start": "node server.js"

Because the MTX sidecar will build the CDS model, you need to configure the build by means of two .cdsrc.json files:

The first .cdsrc.json file goes into the root folder of your project and specifies from which location the CDS files should be collected. The following example demonstrates this:

    "build": {
        "target": ".",
        "tasks": [
                "for": "java-cf"
                "for": "mtx",
                "src": ".",
                "dest": "mtx-sidecar"
                "for": "hana"
    "hana": {
        "deploy-format": "hdbtable"
    "sql": {
        "dialect": "plain"

The second .cdsrc.json file goes into the mtx-sidecar directory. This could look, for example, like:

    "hana": {
        "deploy-format": "hdbtable"
    "build": {
        "tasks": [
                "for": "hana",
                "src": "db",
                "options": {
                    "model": [
                "for": "java-cf",
                "src": "srv",
                "options": {
                    "model": [
    "odata": {
        "version": "v4"
    "requires": {
        "db": {
            "kind": "hana",
            "multiTenant": true,
            "vcap": {
				"label": "service-manager"
        "uaa": {
            "kind": "xsuaa"

Now, add the mtx-sidecar module to your mta.yaml file:

# --------------------- SIDECAR MODULE -----------------------
-  name: mtx-sidecar
# ------------------------------------------------------------
   type: nodejs
   path: mtx-sidecar
      memory: 256M
      disk-quota: 512M
   -  name: xsuaa
   -  name: service-manager
   -  name: sidecar
         url: ${default-url}

The mtx-sidecar module requires the XS UAA and Service Manager services. Also you need to provide its URL to be able to configure the URL in the service module

Wiring It Up:

To bind the previously mentioned services and the MTX sidecar to your Cloud Application Programming Model Java application, you could use the following example of the srv module in the mta.yaml file:

# --------------------- SERVER MODULE ------------------------
-  name: multitenantapp-srv
# ------------------------------------------------------------
   type: java
   path: srv
      memory: 1024M
      disk-quota: 256M
      buildpack: sap_java_buildpack
      builder: custom
        - mvn clean package -DskipTests=true
      build-result: target/*-exec.jar
   -  name: service-manager
   -  name: xsuaa
   -  name: saas-registry
   -  name: sidecar
   -  name: app
   -  name: srv
         url: '${default-url}'

Deploy to SAP Business Technology Platform:

Please follow below steps to deploy to SAP BTP (Cloud Foundry) Trial landscape.

  • Create an SAP HANA Cloud Instance in your SAP Business Technology Platform space.

Please follow below screenshots to create an instance and in step 3, please select allow all IP addresses as shown in the screenshot. You can select all default values and click on create. This will take few minutes.

Create SAP HANA Cloud Instance:

Screenshot 1:


Create HANA Cloud Instance

Screenshot 2:



Note: once the SAP HANA Cloud instance is created, please copy the instance id and replace the value in as follows.

@Before(event = MtSubscriptionService.EVENT_SUBSCRIBE)
public void beforeSubscription(MtSubscribeEventContext context) {
	new InstanceCreationOptions().withProvisioningParameters(
		Collections.singletonMap("database_id", <<INSTANCE ID>>)));
  • Run mbt build
  • Run cf login
  • Run cf deploy mta_archives/multitenantapp_1.0.0-SNAPSHOT.mtar

Sample Demo:

Once the deployment is successful, you should see all the 4 apps in started status as below.


Apps Deployed

Create a new SubAccount to onboard a new tenant as shown below.


SubAccount creation

Subscribe to the Multi Tenant App as below.


Subscribe to application


Subscription Success

Go to application and you will see route does not exists error as below.


Go To Application


Route does not exists

Add tenant url as a new application route and map tenant URL to AppRouter URL as shown below.


Add Route


Map Route

Access the application using the newly created tenant URL and this should display a welcome page as below. Click on Get My Tenant Data link and should authenticate the user against SAP Default IDP (enabled by default) and should show all Book entries from the tenant database as below.




Books Listing no data

Add a new book entry to tenant database and check the same using Get My Tenant Data link as shown below.

First we need to request for CSRF token.


Get CSRF Token

Post a book entry.


Post book entry

Refresh the page and check if data is retrieved.


Books Listing with data



In this blog, I have tried to demonstrate how to build multitenant application using Cloud Application Programming Model Java SDK and cds-mtx node module. You can find working example at

Please note that, I have developed and tested this example using SAP Business Application Studio and SAP BTP Trial landscape.

Links and Further Reading:

Capire >> Multitenancy

SAP Business Technology Platform >> Development >> Development in the Cloud Foundry Environment >> Developing Applications and Services >> Developing Multitenant Applications in the Cloud Foundry Environment

Cloud Application Programming Model Samples for Java

SAP HANA Academy >> SAP BTP Multitenant Business Applications


How to obtain support/help:

Please provide your feedback, thoughts in the comments section.







Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Silas Rocha
      Silas Rocha

      Do you have some example on how to do that using nodejs ?

      Author's profile photo Lucia Wu
      Lucia Wu

      Hi Kumar, WHEN I download your code, and deploy to my btp, but error when I subscribe it.

      I just update


      two palce:
      xsappname: multitenantapp-dev
      one palce:
      appName: multitenantapp-dev

      Author's profile photo Tiller Young
      Tiller Young

      Very interesting option. I learned a lot of new things for myself. If someone does not succeed in something, you can enroll in courses so that there is more understanding, knowledge and practice. And, if everything is completely bad, then only services should be ordered and you can not even do programming.

      Author's profile photo Priyadarshini Ashokan
      Priyadarshini Ashokan

      In my understanding 'multitenantapp-srv' & 'mtx-sidecar' seem to be hosted as different applications  in different containers? How is this exactly a sidecar deployment, should a sidecar share the same container as the primary application?