69 · MTA Introduction

Understand MTA modules, resources, and dependencies. Write a valid mta.yaml for a CAP + SPA + AppRouter stack.

Episode 69 — MTA: Multi-Target Applications

What you'll learn

Why this matters

A real BTP application is not one Cloud Foundry app — it is a collection of parts: a Node.js CAP service, a React frontend, an AppRouter, and a set of bound services (XSUAA, HANA, Destination, Object Store). Deploying each part manually is error-prone and hard to reproduce. The MTA (Multi-Target Application) standard packages everything into a single deployable archive (.mtar) with a declarative descriptor. One command deploys or re-deploys the whole stack in the right order with the right bindings.

MTA concepts

Concept What it is
Module A deployable artifact — a CF app, a content deployer
Resource A managed service or existing CF service
Dependency A requires / provides edge between modules and resources
Parameter A value injected into module/resource config at deploy time
mta.yaml The declarative descriptor of the whole MTA
.mtar The built archive containing all modules + the descriptor

Minimal mta.yaml for a CAP + SPA app

_schema-version: '3.1'
ID: my-cap-app
version: 1.0.0
description: My CAP Application

modules:

  # ── CAP Service ─────────────────────────────────────────────────────────────
  - name: my-cap-app-srv
    type: nodejs
    path: .
    parameters:
      buildpack: nodejs_buildpack
      memory: 512M
      disk-quota: 1G
    build-parameters:
      builder: npm
      build-result: gen/srv
      ignore: [node_modules/, .env]
    requires:
      - name: my-xsuaa
      - name: my-hana
      - name: my-destination
    provides:
      - name: srv-api
        properties:
          srv-url: '${default-url}'

  # ── HTML5 App UI Deployer ────────────────────────────────────────────────────
  - name: my-cap-app-ui-deployer
    type: com.sap.application.content
    path: frontend
    requires:
      - name: my-html5-repo-host
        parameters:
          content-target: true
    build-parameters:
      build-result: dist
      requires:
        - name: my-cap-app-ui
          artifacts:
            - dist.zip
          target-path: resources/

  # ── AppRouter ───────────────────────────────────────────────────────────────
  - name: my-cap-app-approuter
    type: approuter.nodejs
    path: approuter
    parameters:
      memory: 256M
      disk-quota: 256M
    requires:
      - name: my-xsuaa
      - name: my-html5-runtime
      - name: my-destination
      - name: srv-api
        group: destinations
        properties:
          name: cap-backend
          url: '~{srv-url}'
          forwardAuthToken: true

resources:

  - name: my-xsuaa
    type: org.cloudfoundry.managed-service
    parameters:
      service: xsuaa
      service-plan: application
      path: ./xs-security.json
      config:
        xsappname: my-cap-app-${org}-${space}
        tenant-mode: dedicated

  - name: my-hana
    type: com.sap.xs.hdi-container
    parameters:
      service: hana
      service-plan: hdi-shared

  - name: my-destination
    type: org.cloudfoundry.managed-service
    parameters:
      service: destination
      service-plan: lite

  - name: my-html5-repo-host
    type: org.cloudfoundry.managed-service
    parameters:
      service: html5-apps-repo
      service-plan: app-host

  - name: my-html5-runtime
    type: org.cloudfoundry.managed-service
    parameters:
      service: html5-apps-repo
      service-plan: app-runtime

Key patterns explained

provides / requires with group: destinations: The AppRouter needs to know the CAP service URL at deploy time. The CAP module publishes its URL under srv-api. The AppRouter consumes it in a destinations group, which AppRouter reads as an environment variable destinations — a JSON array of route configs.

${default-url}: A parameter placeholder that expands to the CF app route assigned at deploy time. Never hardcode URLs in mta.yaml.

${org} and ${space}: Namespacing XSUAA xsappname per org/space prevents collisions when the same app is deployed to multiple spaces (dev, test, prod).

Building the MTA

# Install MTA Build Tool
npm install -g mbt

# Build the .mtar archive
mbt build -t ./

# Output: my-cap-app_1.0.0.mtar

mbt runs each module's build steps (npm build for Node.js, npm run build for Vite), then packages everything into a single archive.

Common mistakes

Mistake Fix
Hardcoding space/org-specific URLs Use ${default-url}, ${org}, ${space} parameters
Missing ignore: [node_modules/] Including node_modules bloats the archive
Forgetting the HDI deployer module HANA tables are not created unless you include a hdi-deployer module
requires without provides The consuming module will fail — check that the provider declares the property group
_schema-version mismatch Use 3.1 for modern MTAs; older schemas lack some features

Checkpoint ✓

You understand the MTA concepts of modules, resources, and dependencies. You can write a valid mta.yaml for a CAP + SPA + AppRouter stack, use parameter placeholders for URLs and service names, and build a deployable .mtar archive with mbt build.

Sign in for progress tracking & Q&A →