Skip to Content
Technical Articles
Author's profile photo Wouter Lemaire

Split MTA into backend & frontend – Managed AppRouter


When building applications for the SAP Business Technology Platform (BTP) containing a database layer, API layer and UI layer we have two options. The first option would be to create each part separated and deploy it independent from each other to BTP. The other option would be to keep different modules that share the same lifecycle together by using the concept of MTA. MTA is designed to develop all different modules as one big application and deploy it together to BTP. MTA projects will automatically instantiate required services and bind it to the modules that consume them.

Here you have the official definition of MTA:

A Multitarget application (MTA) is logically a single application comprised of multiple parts created with different technologies, which share the same lifecycle.

The developers of the MTA describe the desired result using the MTA model, which contains MTA modules, MTA resources, and interdependencies between them. Afterward, the validates, orchestrates, and automates the deployment of the MTA, which results in Cloud Foundry applications, services and SAP specific contents. For more information about the Multitarget Application model, see the official The Multitarget Application Model specification.


It states “share the same lifecycle”, the database and API layer often have similar lifecycle but this is not always the case. It can be perfectly possible that the API part and UI have a complete different lifecycle. In that case you maybe want to split up the MTA. Another reason could that you have different teams working on different parts of the app, a team working on the backend and one on the frontend. You maybe don’t want that a backend developer starts changing the frontend or the other way around. There might be even more reasons to split your MTA.

The question remains, how to connect the frontend to the backend when they are part of different MTA projects? Just like you have different reasons for splitting your MTA, there are different solutions to connect both MTA projects. In this blog I’m going to show how you can split your backend from the frontend using the managed AppRouter in BTP by only using MTA configuration.

Let’s start by creating the backend MTA:

(I’m going to use the Business Application Studio because it comes with a generator that has some valuable AppRouter configuration for the managed AppRouter)

Create Backend service

With “Backend service” I mean the database and api layer together. This goes hand in hand most of the time so it doesn’t harm to keep this together.

For creating the backend, I used the SAP Cloud Application Programming model, also known as CAP. Starting by using the “CAP Project” generator in BAS:

In the generator I provide a name for my project, select my favorite runtime and enable deployment for the database part to HANA with MTA configuration for deploying to CloudFoundry.

On top of that, I also enable the option to include the basic sample files just for testing purpose.

For demo purpose I simply keep everything as generated from the sample files. I do enable authentication on my service for security reasons by following the steps in the CAP documentation:

Some parts of the documentation are done by the mta configuration. For example, the xsuaa configuration comes from the generator already.

Next, I make authentication required by adding the following in the “cat-service.cds”

That’s actually it for the backend service!

For making the backend service available to other applications, I need some additional configuration. This configuration can be easily generated by adding a Fiori app to the CAP project. It also gives the possibility to test if everything works fine. For this I still used the deprecated generator “SAP Fiori Freestyle Module”:

Reason, why I use the deprecated generator: 

Give it a name:

Select the basic template:

Immediately add the approuter config, I want to use the “Managed Approuter” and provide a unique name my project: (It’s important to not use an existing one, it will overwrite the existing one.)

Enable authentication an provide a namespace:

Provide a name for the main view and add a data service

This is the benefit when running the generator for a UI module in the same mta. You can simply connect the UI module to the service in the generator by selecting “workspace”:

And here you can select the service from your CAP project:

I also added a list to the main view to see the result of the CAP service.

In the end, this generator will add configuration to the mta.yaml file which will create a destination for the CAP service:

This destination is needed to access the CAP service from other applications outside this MTA project.

You can find the full code in this repo:


Create separated Frontend app

Off course, by frontend I mean a Fiori UI5 application :). Instead of generating a new UI5 app in the same MTA, I’m going to create a completely new MTA project with only my UI5 app. This time I used the newly released “SAP Fiori application” generator:

I selected the same template as in the deprecated generator:

As Data source I selected “None”. Currently I did not found a way to connect to my CAP service by using the generator:

I filled in all the project attributes and enabled deployment and flp configuration:

For some reason I got stuck in the generator at the time writing this blog post. Luckily, I was able to finish the wizard before taking screenshots and notes. If the problem in the generator still occurs for you, I raised this as a question for follow up:

For now, I continued using the deprecated generator. This generator includes the steps for the configuration of the approuter. If you use the new generator, you have to run a second generator for adding the approuter config: (You can also do this manually but it’s not that easy)

I’m going to use the “Managed Approuter” again. Be aware that the id for the managed approuter needs to be unique. Otherwise it will overwrite other html5 repositories.

This generator will add the following configuration to your project. This is the key to connect the UI of this MTA project to the service in the other MTA project:

This configuration will create a destination for the app-host and xsuaa instance that’s being used for the Fiori app in combination with the sap cloud service id. These generated destinations are needed for the Launchpad service to find your app in the HTML5 content provider. You can find detail explanation in the sap help documentation:


I changed this generated config for two reasons:

  • Reusing service instances, some services are already instantiated by the config of the first project (CAP project with Fiori app included).
    • The destination service from the Fiori app in the CAP project can be used in this Fiori app as well. It’s not needed to create a new instance of the Destination service
    • This is not the case for all of them, the app-host service needs to be a new instance. Otherwise it will overwrite your other app.
    • I’m going to reuse the xsuaa service which I’m going to explain in the next point. In case you have completely separated apps, it is better to create a new xsuaa instance. This will allow you to maintain the scopes dedicated for this app in the app-security file.
  • Using my CAP service from the first project
    • I want to consume my CAP service from my first project in my second separated fiori app. For this, the service and the UI app need to be connected to the same XSUAA instance. Downside, both share the same xs-security.json file. Best is to keep them in sync because each deploy will overwrite the previously deployed xs-security.json.


Let’s start the magic 🙂


  1. Change the destination service, go to “resources” in the mta.yaml and change the “service-name” of the destination service to the same as the one in the first project:

2. Change the service instance name of the xsuaa service to the same as in the first project:

3. Change the “xsappname” in xs-security.json to the same as the other project. Otherwise the deploy will fail because it’s not possible to update the name in an existing xsuaa instance.

4. Add the route to the destination of the CAP service in the xs-app.json (this destination was generated from the mta config in the CAP project)

5. Add tile config (might be done already by the generator)

6. Add the datasource config to the CAP service:

7. Add the ODataModel config:

8. Show the books entity as a list in the  main view:

9. The app is ready for building and deploying to BTP CloudFoundry


The full project is available on GitHub:

Result in BTP Launchpad Service

As soon as the applications are deployed, you have to refresh the “HTML5 Apps” content provider in the Launchpad service and you will find them in the Content Exporer:

First refresh the HTML5 Apps provider:

Now, you will see your app in the “Content Explorer”:

Add the app to a catalog, group and role to see it on the launchpad:

When you click on the tile, the app from one MTA project will open and show data from the other MTA project:

A more detailed tutorial on how to integration your app in the launchpad service:


The complete group of tutorials:


I created a CAP project with a database, api and ui layer. The API was made accessible only for authenticated users. On top of that, I created a UI only app that consumes the API from the CAP project. All of this described in different MTA’s. The key is to bind both MTA projects to the same xsuaa service instance.

This setup can be used in case you want to separate the MTA project into a backend and frontend part for whatever reason.

I shared my example projects on GitHub:


I had this requirement for splitting up the MTA into backend and frontend already a few times for different reasons. Sometimes because of different types of developers, sometimes because one API is consumed by several apps and all have a different lifecycle or just to improve the build and deploy time of the MTA. Hope this can be valuable for you as well!


Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Fabian von Allmen
      Fabian von Allmen

      Hi Wouter

      Thanks for the great blog post. I was trying to achieve the same this weekend and finally got it running too 🙂

      I noticed one difference between your and my approach. Instead of defining the same resources (e.g. uaa) again with type `managed-service` I changed it to `existing-service` in the UI part. In this case the resource will be ignored but still can be used and it is totally clear which part of the app is responsible for the service itself.

      Best regards, Fabian

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Indeed, that’s a good one! Thanks for sharing!

      Author's profile photo Matthew Reddy
      Matthew Reddy

      Great blog, Wouter! I have a question regarding xs-security, to make sure I grasp the approach. In your example, you replicated the xs-security from one MTA to the other. In the event you were to add more scopes aside from the token exchange one, would you have to add identical scopes/roles to both in order to pass the expected authorizations from UI to backend?

      I suppose in the event you try the "existing-service" approach ("existing" in UI, "managed" in Service) mentioned by Fabian, you could omit the xs-security from the UI MTA and still utilize the scopes declared in your Service MTA but in your UI code (in the UI's xs-app files, for example). Then you would just need to do the mapping in the IDP and then any xsuaa token you pass from the UI to the Service will have the Service's scopes on it. Is that right?


      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      That’s right.

      Regarding your first question, everything needs to be declared in the mta that is deployed the last. It will always overwrite the previous xs security config. Just to avoid trouble by deploying in a different sequence I keep them identical.

      Author's profile photo Sai Battula
      Sai Battula

      Hi Wouter,

      I have followed same steps, node and ui as separate projects, I am trying on my trial account.

      I have 2 issues:

      1. xxx-db-deployer - not getting started, log says CRASHED.
      2. UI app on load, metadata 500 internal server error.
      3. https://<trial>/$metadata

      Please help.

      Sai Battula.

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Anything in the logs for the 500 error? Hard to tell what goes wrong.. can be many things..

      Author's profile photo Binson Varikkasseril Abraham
      Binson Varikkasseril Abraham

      Hi Sai Battula ,


      I was also getting the 500 internal server error while trying retrieve the service metadata. I performed following changes in my project.


      1. Added "public: true" to "srv-api" of the service module.

      2. added following destination

      - Authentication: NoAuthentication
      HTML5.ForwardAuthToken: true
      Name: <projectname>-srv-api
      ProxyType: Internet
      Type: HTTP
      URL: ~{srv-api/srv-url}
      3. Added following route to xs-app.json in the UI module.
      "authenticationType": "xsuaa",
      "csrfProtection": false,
      "source": "^/catalog/(.*)$",
      "destination": "<projectname>-srv-api",
      "target": "catalog/$1"
      After these changes, I was able to test the application.
      I am not sure whether this is a bug, or missing functionality in the BAS generators.
      Author's profile photo satya dwivedi
      satya dwivedi

      Hi Wouter Lemaire,

      I have divided my application in 2 MTA application, The MTA1 app has only FLP module and Approuter module, the another MTA2 app will have DB,Service & UI5 modules, but MTA 2 is having Approuter but not using it, you can say a blank approuter. After deploying the application BTP. I am getting error in loading metadata 404.$metadata?sap-language=en  
      Error: 404

      below one is working

      but if i remove the /comsatyaapp/~220621184701+0000~ from the url, then it working$metadata?sap-language=en

      I am following below link and in comment section i have explained details .




      Author's profile photo Parthibaraja Vijayan
      Parthibaraja Vijayan

      Hi Wouter Lemaire,

      Thanks for sharing the knowledge.

      We had a similar scenario, where in MTA I: DB & Node.js is residing, and in MTA II: UI & Workflow Modules are there. Able to successfully consume service from MTA I in the UI of MTA II. But the problem is we have to deploy every time to see the changes(Metadata is only not loading in local).

      Please share your thoughts on how to make it work locally as well in BAS.




      Author's profile photo jinqian yin
      jinqian yin

      Hi Wouter Lemaire,

      I had a similar scenario just like you writed but I got a 500 Internal Server Error. There are some difference with you. there is a existing Cap & UI modules created by someone and another MTA UI modules created by another one .Now I want to display a dynamict tile on the MTA UI LaunchPad with the odataService from the existing Cap & UI moduels. I can not change the xsuaa  service  like you talk above because those are not my project.

      I just want to reuse the odataservice of Cap project in the existing MTA UI modules. So I just make some changes in xs-app.json,mta.yaml and manifest.json

      Add a route to xs-app.json and destination service to mta file.




      I add the datasource and dynamic datasource to manifest.json.



      build mta.yaml and deploy it.

      I open the UI from LaunchPad site and get the 500 error below .



      I just want to ask whether the destination service is setted right  beacause I check it sucess on the app destination.  I also can not views the logs in  html5 app that is not display right.

      What is wrong with my configration about destination service.

      Sorry to not write good English grammer and hope your answers.

      Author's profile photo Vikash Rakshit
      Vikash Rakshit

      Hi Jinqian ,


      i am also having the same problem. Were you able to resolve the issue?


      Also the dynamictile is the destination you created at the subaccount level?

      Please respond.




      Author's profile photo Vikash Rakshit
      Vikash Rakshit

      Hi @wouter lemaire,


      Can you please let mw know what is the destination splitAppService-srv-api means here? Is this subaccount level destination.

      I followed your blog but getting 401 not authorized error.


      Can you please help here.




      Author's profile photo Guilherme Sales
      Guilherme Sales

      Hi Wouter Lemaire ,

      Thanks for sharing this.


      In a project I'm currently working on, we have two backend services deployed with a destination service each, just like you showed. How can I use both these destinations on frontend? I wasn't able to connected to multiple destination services on the UI yet.. Do you have any idea of how we could approach that?




      Author's profile photo Saha Ritushree
      Saha Ritushree

      Hello Wouter Lemaire,

      Thanks for sharing a nice blog. I followed this blog and it works as expected , but i encounter the deletion of the fiori apps in the below scenario -

      First Time deployment - This works.

      1 Service App - Deploy Service

      2. Fiori App - Deploy Fiori Apps

      Next Time onwards - 

      If i change the service cap project and deploy it , the fiori apps deployed from 2nd step get undeployed . How do i solve this problem .