Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
Showing results for 
Search instead for 
Did you mean: 
Active Participant
Software-as-a-Service (SaaS) applications are becoming more and more relevant now with the ease of delivery to customers. It is impossible to be successful in SaaS without utilizing the capabilities of multitenancy. There is already a blog that explains how to develop a multitenant application in the Neo environment on SAP Cloud Platform.

In this blog, I'll show you the concept of multitenancy in the Cloud Foundry environment together with a sample multitenant business application that we've developed to showcase the consumption of relevant services in the Cloud Foundry environment on SAP Cloud Platform.

As a prerequisite to this blog, I strongly recommend that you read about the changes to the domain model in SAP Cloud Platform in this blog. It is also assumed that you are already aware of the provider vs. consumer (tenant) concepts of multitenancy.

Let's start off by looking at the components that are needed for a multitenant business application to run in the Cloud Foundry environment in SAP Cloud Platform.


The application owner (the provider of the multitenant application) owns the global account and the subaccount where the application is hosted in SAP Cloud Platform. The application providers can manage subscriptions for their customers in order to use the multitenant features of the SAP Cloud Platform.

Some of the aspects of multitenancy, such as being able to subscribe to applications hosted in other global account and the monetization of the provider applications might be available in the future releases.

The application uses the tenant-aware approuter service, which is the single point-of-entry for the application running on Cloud Foundry environment. The xsuaa service is used for authentication at runtime. The application is registered with SaaS Provisioning (saas-registry) service, which enables the subscription lifecycle events of the application with the consumer tenants.

Which coding approach should you follow?

Multitenancy at the persistence level can be approached in various ways, each with its pros and cons:

  • Column Discriminator - data is stored in the same schema of the same database and tenant details are maintained in a column of the table.

    1. This is the most cost efficient, but separation is very weak and tenant-specific configurations are hard to implement.

    2. Tenant-specific backup and restore is not possible.

  • Schema Separation - data is stored in a separate schema (same database) per tenant.

    1. Cost efficiency and data separation are balanced.

    2. Extension of the schema per tenant is possible.

    3. Requires additional logic for backup and restore to avoid overwriting the entire database in case of schema corruption.

  • Database Instances - every tenant has its own database instance.

    1. Provides the highest level of data isolation as the instances are physically separated.

    2. This entails the highest cost as additional server instances are needed to store each database.

    3. Backup and restore is possible for each tenant.

    4. Underutilization is a possibility.

You can find more details about these approaches in this blog.


From a cost and isolation perspective, the recommended approach is schema separation.

SAP Cloud Platform also provides the automated onboarding/offboarding capabilities for the application provider. This is done through a couple of API callbacks:

  • getDependencies: Provides dependencies to multitenant reuse services.

  • onSubscription: Provides the logic of setting up a tenant in the application (subscription). The same callback is also used to unsubscribe a tenant. This callback must be implemented to return the application URL that suits the tenant host pattern.

The tenant host pattern is used in a manifest.yml file to identify the tenant that is accessing the application.
TENANT_HOST_PATTERN: <<tenant>>-<<appname>>.<<domain>>

Let's look at some coding snapshots


With this blog, we provide a sample application as a reference point to get this fully implemented. This application is about a Product master. The application stores the details of products that are specific to the tenant (customer). The code snapshots that follow based on column discriminator multitenancy.

The sample application contains the following structures and entities:

  • applicationBackend

  • applicationUIModule + appRouter

  • mtConfig (callback implementation)

  • xs-security.json (XSUAA configuration)

  • yml (for Multi-Target Application builds)

The xs-security.json file describes the scope and the tenant-mode:

"xsappname": "inventorymanagementapp",
"tenant-mode": "shared",
"description": "Security profile of inventory management app",
"scopes": [{
"name": "$XSAPPNAME.Callback",
"description": "With this scope set, the callbacks for tenant onboarding, offboarding and getDependencies can be called.",
"grant-as-authority-to-apps": [

  • The xsappname must be unique per the XSUAA instance.

  • The tenant-mode should be set to 'shared' and will require that the TENANT_HOST_PATTERN is declared in the yml file as mentioned earlier.

  • For single-tenant applications, the tenant-mode must be declared as 'dedicated'.

  • The scope mentioned in the above code snapshot must be granted to the tenant-onboarding service as mentioned in the description of the scope. This is only required for automated onboarding of tenants.


To consume a backing service such as SAP HANA, PostgreSQL and so on, the service instance of the backing service must be bound to the application. You can bind the service instances to an application either from the SAP Cloud Platform cockpit or through the CF CLI as mentioned in the

In the UI model of an SAP UI5 application, you must ensure to maintain the approuter dependency in the package.json.
  "dependencies": {
"@sap/approuter": "2.7.1"
"scripts": {
"start": "node node_modules/@sap/approuter/approuter.js"


The configuration for the approuter (xs-app.json) must contain the necessary routes to the UI application and the backend application.

"welcomeFile": "/inventorymanagementui/index.html",
"authenticationMethod": "route",
"logout": {
"logoutEndpoint": "/logout"
"routes": [{
"source": "^/inventorymanagementui/(.*)$",
"target": "$1",
"localDir": "webapp"
}, {
"source": "^/inventorymanagementbackend/(.*)$",
"target": "$1",
"csrfProtection": true,
"authenticationType": "xsuaa",
"destination": "inventorymanagementbackend_api"

The backend application uses the sapxsenv and xssec libraries to parse the environment variables and the JSON Web Token (JWT) strategy, respectively.
var xsenv = require('@sap/xsenv');
var JWTStrategy = require('@sap/xssec').JWTStrategy;

var services = xsenv.getServices({ uaa:'uaa_inventorymanagementapp' });
passport.use(new JWTStrategy(services.uaa));
app.use(passport.authenticate('JWT', { session: false }))

Let's now look at the implementation of the discriminator column as mentioned in the previous sections.

For a simple column-discriminator persistence, the query to retrieve the tenant-specific data would look like this:
var selectAllProductsQuery = "SELECT * FROM products WHERE \"tenant_id\" = " + tenant_id;

For inserting values, the statement would look like this:
"INSERT INTO products (\"product_name\",\"product_description\",\"supplier_name\",\"price\",\"available\",  \"quantity\",\"tenant_id\")" +

For detailed documentation about these steps, refer to Developing Multitenant Business Applications in the Cloud Foundry Environment on SAP Help Portal.

In subsequent blogs that we'll be posting, you'll learn about the recommended schema-based multitenant persistency on an SAP HANA database.


References and sequels:

Sample code - Developing a SaaS Multitenant Business Application on SAP Cloud Platform Cloud Foundry Environment

Sample Code 2 - Multitenancy on HANA

Blog - Architecture overview

Blog - SaaS Provisioning service and its consumption