Skip to content

    Migration from Old MTX

    Towards new multitenancy capabilities

    Explains how to migrate from @sap/cds-mtx (aka Old MTX) to @sap/cds-mtxs (‘streamlined’ MTX)

    This guide is still work in progress and will be updated.


    Functional Differences

    Before you start to migrate towards the ‘streamlined’ MTX, read about the differences compared to the old MTX.


    For ‘streamlined’ MTX, we have no support for the following:

    • async extensibility (push) [temporary limitation]
    • undeploy [temporary limitation]
    • hdbmigrationtable for extensibility
    • setup of extension projects via cds extend
    • custom content


    For ‘streamlined’ MTX, we have no support for the following:

    • diagnose API [temporary limitation]
    • configurable scopes
    • tenant-individual basemodel version stored


    • served event is not emitted if you use your own bootstrap in server.js w/o delegating to cds.server
    • When filtering all services to get your own application services, you will catch the cds.xt.ModelProviderService as well.

    Adapt Project Configuration

    To switch your project to ‘streamlined’ MTX, perform the following steps:

    1. Remove @sap/cds-mtx:
       npm remove @sap/cds-mtx
    2. Add @sap/cds-mtxs:
      npm add @sap/cds-mtxs
    3. Open your package.json and add the following:
       "cds": {
           "requires": {
               "multitenancy": true,
               "extensibility": true // if needed

    Build Configuration

    cds build will create the correct cloud deployment contents if your project matches the default layout as proposed for CAP projects and created by cds init.

    Note: Additional changes might be required if custom build tasks are configured. So, check if defaults would fit and if a custom build configuration is really needed. cds build logs the effective build configuration to the console. The default values will kick in for all build task properties that have not been configured.

    Configuration for Custom Build Tasks

    In case you need custom build tasks, make sure the CDS models for multitenancy, extensibility and toggles are defined as options.model in your build configuration. They represent the CDS model description of the required MTX Services. Otherwise, database artifacts will be missing or required services couldn’t be loaded in the cloud environment.

    "cds": {"build": {"tasks": [
      {"for": "nodejs", "options": {"model":[...,"@sap/cds-mtxs/srv/bootstrap","@sap/cds-mtxs/db/extensions"]}}
    MTX Service Required CDS Model
    requires.multitenancy: true "@sap/cds-mtxs/srv/bootstrap"
    requires.extensibility: true "@sap/cds-mtxs/srv/bootstrap","@sap/cds-mtxs/db/extensions"
    requires.toggles: true "@sap/cds-mtxs/srv/bootstrap"

    Handler Registration

    A typical handler registration in server.js now looks like

    cds.on('served', async () => {
      const { 'cds.xt.SaasProvisioningService': provisioning } =
      const { 'cds.xt.DeploymentService': deployment } =
      await provisioning.prepend(() => {
        provisioning.on('UPDATE', 'tenant', async (req, next) => { ... })
        provisioning.on('dependencies', async (req, next) => { ... })
      await deployment.prepend(() => {
        // previously this was `upgradeTenant`
        deployment.on('upgrade', async (req) => {
          // HDI container credentials are not yet available here
        // previously this was `deployToDb`
        deployment.on('deploy', async (req) => {
          const { tenant, options: { container } } =

    Here’s what has changed:

    • ProvisioningService changed to cds.xt.SaasProvisioningService
    • DeploymentService changed to cds.xt.DeploymentService
    • Use cds.on('served') instead of cds.on('mtx').

    Saas Registry Endpoints

    For Node.js, the saas-registry endpoints in mta.yaml need to be changed to .../-/cds/saas-provisioning/...:

      service: saas-registry
          getDependencies: ~{mtx-api/mtx-url}/-/cds/saas-provisioning/dependencies
          onSubscription: ~{mtx-api/mtx-url}/-/cds/saas-provisioning/tenant/{tenantId}

    Java-based projects do not need to modify their saas-registry configuration.


    Scopes ExtendCDS and ExtendCDSdelete have changed to cds.ExtensionDeveloper.

    • Communicate to customer admins and extension developers to add the new scope to their role collection.
    • Adjust the documentation for the SaaS application accordingly.

    Use Local Sandbox

    • Run locally (w/ sqlite)
    • Try build for SAP HANA deployment w/ cds build
    • Call MTX endpoints locally

    Migrate Tenant Content of Existing Applications

    Depending on the MTX features that your existing application has used, you need to execute some steps to move your data to the persistence used by @sap/cds-mtxs.

    Configuration Changes Only

    In case you only used the multitenancy features such as subscription/unsubscription, you just need to make the configuration changes described earlier.

    When does this scenario apply?

    • Your application doesn’t support extensibility.
    • You don’t need to read all tenant IDs or the tenant metadata using GET /-/cds/saas-provisioning/tenant/ or GET /-/cds/saas-provisioning/tenant/<tenantId>.

    The tenant metadata is the data that is sent to the MTX API by the SAP BTP SaaS Provisioning Service on subscription, similar to this:

        "subscriptionAppId": "...",
        "subscriptionAppName": "..." ,
        "subscribedTenantId": "...",

    See project configuration.

    Migration of tenant Metadata

    If your application needs access to the tenant list or tenant metadata, you need to update this data for @sap/cds-mtxs.

    When does this scenario apply?

    • Your application doesn’t support extensibility.
    • Your application needs to read all tenant IDs or the tenant metadata using GET /-/cds/saas-provisioning/tenant/ or GET /-/cds/saas-provisioning/tenant/<tenantId>.

    Run the Migration Script

    The migration script is part of @sap/cds-mtxs. You can call it locally or during application deployment. Before running the script, you need to make the configuration changes mentioned earlier.

    Run it in the application environment so that it can launch the @sap/cds-mtxs services such as cds.xt.DeploymentService.

    It also needs access to the application bindings. That means, when running locally, it has to run in hybrid mode.

    To run the migration for all or a set of tenants, you need to run:

    cds migrate <tenant>[,<tenant>]|"*"

    The option --dry allows you to perform a dry run, database won’t be changed.

    Please keep in mind that, depending on the number of tenants, the script requires some time to run. This is important when you consider to run it in combination with the application deployment.

    Migration of Extensions

    If your application supports extensibility, you’ll also need to update the existing extensions for @sap/cds-mtxs. You can do this with the same migration script mentioned earlier.

    In addition, you can use the migration script to save the content of the subscribers’ extension projects.

    Using parameter -d, you can specify a directory that is used by the script to store the existing, migrated extension projects.

    cds migrate <tenant>[,<tenant>]|"*" -d <your directory>

    Separate Extensions Based on Extension File Names

    The concept of extensions has slightly changed with @sap/cds-mtxs. Extensions sources are no longer stored in the backend. Instead, each extension gets a tag and the extension is stored as csn with the tag as key. When running the migration script, all extension files are compiled to one csn and are stored with a default tag: migrated.

    You can change the default tag by passing your own tag using the --tag parameter:

    cds migrate "*" -d migration_projects --tag "mytag"

    In addition, you can separate your extensions into several csn-files with different tags. For example, if your original extension files follow a pattern, you can do so by passing parameter --tagRule with a regular expression.

    Let’s use the following extension project structure:

    Extension project example

    You can split your extensions as follows:

    cds migrate "*" -d migration_projects --tagRule "(?:ext_|extension_)(.*)\.cds"

    As a result, you get two extensions with tags id_1 and id_2. The tag is taken from the first captured group of the regular expression.

    Best Practice:
    It’s not always easy to find the right regular expression. To verify if the result meets your expectations, you can make a dry-run:

    cds migrate "*" -d migration_projects --tagRule "(?:ext_|extension_)(.*)\.cds" --dry

    You can find the result in the folder migrated_projects.