L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Design et création · SKILL.md

sap-btp-saas

sap-btp-saas

SAP BTP SaaS Registry — multi-tenant application design, subscription management, tenant onboarding/offboarding, HDI container isolation, XSUAA tenant mode, CAP SaaS patterns. Use when building multi-tenant apps on BTP or implementing SaaS subscription flows.

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: sap-btp-saas description: > SAP BTP SaaS Registry — multi-tenant application design, subscription management, tenant onboarding/offboarding, HDI container isolation, XSUAA tenant mode, CAP SaaS patterns. Use when building multi-tenant apps on BTP or implementing SaaS subscription flows. trigger: keywords: - btp saas registry - multi-tenant application btp - tenant onboarding subscription - hdi container per tenant - xsuaa tenant mode shared dedicated - cap saas multi-tenant - saas subscription callback intent: "Build or configure a multi-tenant SaaS application on SAP BTP"

SAP BTP SaaS Registry

Multi-tenant application architecture on SAP BTP — tenant isolation, subscriptions, lifecycle management.

Prerequisites

  • SAP BTP provider subaccount with Cloud Foundry enabled
  • cf CLI installed and authenticated
  • Entitlements for: SaaS Registry, XSUAA, HANA HDI (or managed HANA)
  • CAP application deployed and working in single-tenant mode first
  • Admin access to BTP Cockpit for consumer subaccount subscription

Architecture Overview

Provider Subaccount
├── SaaS Registry  (subscription management)
├── XSUAA (tenant-mode: shared)
├── HANA HDI (per-tenant containers)
└── CAP App (single deployment, tenant-aware routing)
    ├── onSubscription callback → creates HDI container
    ├── onUnsubscription callback → drops HDI container
    └── Tenant-aware DB connections via @sap/cds-mtxs

Steps

1. Configure XSUAA for Multi-Tenancy

// xs-security.json
{
  "xsappname": "my-saas-app",
  "tenant-mode": "shared",
  "scopes": [
    { "name": "$XSAPPNAME.User" },
    { "name": "$XSAPPNAME.Admin" }
  ],
  "role-templates": [
    { "name": "User", "scope-references": ["$XSAPPNAME.User"] },
    { "name": "Admin", "scope-references": ["$XSAPPNAME.Admin", "$XSAPPNAME.User"] }
  ]
}
cf create-service xsuaa application my-xsuaa -c xs-security.json

2. Create SaaS Registry Service Instance

// saas-registry.json
{
  "appName": "my-saas-app",
  "appUrls": {
    "getDependencies": "https://my-app.cfapps.us10.hana.ondemand.com/callback/v1.0/dependencies",
    "onSubscription": "https://my-app.cfapps.us10.hana.ondemand.com/callback/v1.0/tenants/{tenantId}"
  }
}
cf create-service saas-registry application my-saas-registry -c saas-registry.json

3. Implement CAP Subscription Callbacks

// srv/saas-handler.js
const cds = require('@sap/cds');

module.exports = class SaaSHandler extends cds.ApplicationService {
  async init() {
    // onSubscription — called when consumer subscribes
    this.on('UPDATE', '/saas/subscription', async (req) => {
      const { subscribedTenantId, subscriptionAppId } = req.data;
      // CAP auto-provisions HDI container via mtxs
      return { subscriptionUrl: `https://${subscribedTenantId}.my-app.com` };
    });

    // onUnsubscription — called when consumer unsubscribes
    this.on('DELETE', '/saas/subscription', async (req) => {
      const { unsubscribedTenantId } = req.data;
      // CAP auto-deprovisions tenant container
      return {};
    });

    await super.init();
  }
};

4. Configure CAP for Multi-Tenancy

// package.json (excerpt)
{
  "cds": {
    "requires": {
      "db": { "kind": "hana", "multi-tenant": true },
      "auth": { "kind": "xsuaa" }
    },
    "mtx": {
      "plugin": true
    }
  }
}

5. Deploy and Register the SaaS App

mbt build -t ./mta_archives
cf deploy ./mta_archives/my-saas-app_1.0.0.mtar

# Verify SaaS Registry knows the app
cf service my-saas-registry

6. Consumer Subscribes (BTP Cockpit)

  1. Consumer opens their subaccount in BTP Cockpit
  2. Navigate to Instances and Subscriptions → Create → select the SaaS app
  3. Click Subscribe
  4. SaaS Registry calls onSubscription callback → CAP provisions HDI container
  5. Consumer accesses app at https://<consumer-subdomain>.my-app.com

Tenant Isolation Patterns

  • Shared schema (discriminator column): low isolation, WHERE tenant_id = ? — for small tenants
  • Shared DB, separate schemas (HDI per tenant): medium isolation — default CAP approach
  • Separate DB per tenant: high isolation — for compliance-heavy tenants
  • Separate deployment: maximum isolation — premium tier only

Pitfalls

#PitfallCauseSolution
1Subscription callback times outCallback takes >30 seconds (HDI provisioning is slow)Keep callback async; return 200 immediately, provision in background job
2403 Forbidden on tenant accessXSUAA tenant-mode not set to sharedRecreate XSUAA instance with "tenant-mode": "shared" in xs-security.json
3HDI container creation failsHANA instance out of memory or too many containersMonitor HANA memory; consider shared-schema for small tenants
4Consumer can't find app in BTP cockpitSaaS Registry not deployed or appName mismatchVerify cf service my-saas-registry shows "create succeeded"; check appName matches MTA ID
5Tenant data bleeds between tenantsMissing tenant filter in CDS or raw SQL queriesAlways use CAP service layer (auto-tenant-filtered); never bypass with raw SQL
6Offboarding leaves orphaned containersonUnsubscription callback errors silentlyAdd try/catch + logging in DELETE handler; verify container dropped via HANA cockpit
7getDependencies callback missingNot implemented in CAP serviceImplement GET /callback/v1.0/dependencies returning [{ appId, appName }]

Verification

# Check SaaS Registry service is provisioned
cf service my-saas-registry

# Check app is running and callbacks respond
curl -s https://my-app.cfapps.us10.hana.ondemand.com/callback/v1.0/dependencies \
  -H "Authorization: Bearer $TOKEN"

# List subscribed tenants
cf service my-saas-registry  # shows bound app

# In BTP Cockpit (provider subaccount):
# → Instances and Subscriptions → verify app appears with "Subscribed" consumers

Confirm:

  • Consumer subaccount can subscribe via BTP Cockpit
  • After subscription, HDI container exists in HANA (check via HANA cockpit)
  • Tenant URL returns app with correct tenant-specific data
  • Unsubscribe triggers container cleanup (no orphaned HDI containers)
Skills enregistrées