December 20, 2025 / admin

TL;DR 

Ripping out your ECC monolith in one epic weekend is the fastest path to CFO heartburn. A safer route is progressive carve-out: lift one business capability at a time into a Cloud Application Programming (CAP) microservice running on SAP BTP, connect it back to ECC with Event Mesh, and retire legacy code sprint by sprint. We share the exact playbook our Micro-GCC squad used to extract “Sales Pricing” from 300 000 lines of Z-code—with zero plant downtime and a 43 % latency improvement. All CDS, mta.yaml, and Terraform snippets included.

Why “Lift-and-Shift” Fails in SAP Land 

Typical big-bang plan: clone ECC database, refactor Z-code in S/4 sandbox, schedule 48-hour outage.
Reality: transports collide, IDoc queues pile up, month-end close panics.

Key blockers:

  1. Elephant tables (MARA, VBAK) resist parallel updates.
  2. Custom Z-code couples UI, business logic, and DB calls in one lump.
  3. Cut-over windows for global plants must be < 15 min.

Progressive carve-out solves this by:

  • Picking a well-bounded domain (“Sales Pricing”).
  • Creating a CDS model + CAP service in BTP.
  • Publishing change events from ECC to Event Mesh.
  • Gradually re-routing traffic—no nuclear weekends.

Reference Architecture 

sql

CopyEdit

      ECC (Blue)          Event Mesh           BTP (Green)

   +—————-+   +—————+   +——————+

   |  SD Z_PRICING  |–>|  SD.PRICING.* |–>| CAP Service v1   |

   | (ABAP Module)  |   +—————+   |  /pricing/* OData|

   +—————-+                       +——————+

        ↑    |                                     ↑

        |    | SAP SLT (real-time)                 |

        |    +————————————-+

        |                                          

   Legacy UI5 App           New UI5/Fiori

  • SLT replicates VBAK/VBAP delta to HANA Cloud.
  • CDS model maps to new HANA Cloud schema.
  • CAP service (Node.js) exposes OData V4 for Fiori & external APIs.
  • Event Mesh channels SD.PRICING.UPDATED messages; CAP subscribes and updates cache.

Step-switch: gateway route toggles /pricing/* to CAP when E2E tests green.

Step-by-Step Carve-Out 

3.1 Scope the Domain

Rule of thumb: choose a business capability with ≤ 3 BAPIs and ≤ 5 tables.
For Sales Pricing we touched VBAK, VBAP, KONV and three custom Z-tables.


3.2 Create CDS Model

db/schema.cds

cds

CopyEdit

namespace sd.pricing;

entity SalesOrder {

  key SalesOrderID : String(10);

  NetValue         : Decimal(15,2);

  Currency         : String(5);

}

entity PricingCondition {

  key CondID    : Integer;

      SalesOrderID : Association to SalesOrder;

      Amount       : Decimal(15,2);

      CondType     : String(4);

}

Run:

bash

CopyEdit

cds deploy –to hana


3.3 Build CAP Service

srv/pricing-service.js

js

CopyEdit

module.exports = srv => {

  const { SalesOrder, PricingCondition } = srv.entities

  srv.before(‘CREATE’, PricingCondition, validateAmounts)

  srv.on(‘reprice’, async req => {

    const so = await SELECT.one.from(SalesOrder).where({ SalesOrderID: req.data.id })

    // call external pricing engine, update NetValue …

    return so

  })

}

mta.yaml adds requires: [ hana, eventmesh ].


3.4 Event Mesh Subscription

event-mesh.json

json

CopyEdit

{

  “source”: “ECC”,

  “events”: [

    { “name”: “SD.PRICING.UPDATED”, “namespace”: “sap.s4”, “version”: “v1” }

  ]

}

CAP srv/pricing-sub.js

js

CopyEdit

module.exports = srv => {

  const { PricingCondition } = srv.entities

  srv.on(‘sap.s4/SD.PRICING.UPDATED’, async msg => {

    await UPDATE(PricingCondition).where({CondID: msg.data.id}).set(msg.data)

  })

}

Latency ECC → CAP cache: ≤ 300 ms (tested 95th percentile).


3.5 CI/CD Pipeline

jenkinsfile

groovy

CopyEdit

stage(‘Build’) { sh ‘mbt build’ }

stage(‘Deploy’) {

  withCredentials([file(credentialsId: ‘btp.json’, variable: ‘BTPCRED’)]) {

    sh ‘cf deploy mta_archives/pricing_1.0.0.mtar –json’

  }

}

stage(‘Smoke’) { sh ‘npm run smoke’ }

Smoke tests hit /pricing/$metadata plus /reprice.


3.6 Route Traffic

In SAP APIM:

yaml

CopyEdit

routes:

  – match: /pricing/**

    target: cap-green

    weight: 20

  – match: /pricing/**

    target: ecc-blue

    weight: 80

After 24 h of green logs, flip weights to 100/0. Rollback = YAML revert.

Latency & Cost Benchmarks 

MetricECC Z-RFCCAP Microservice
p95 Read Latency520 ms297 ms
p95 Write Latency640 ms335 ms
Monthly Infra €N/A (on-prem)€420 (BTP, 2 GB HANA Cloud)

Savings: dev hours (fewer OSS notes), faster user response, and clear path to mobile APIs.

Case Study Snapshot 

Industrial OEM needed real-time price quotes in a dealer portal.

  • Before: RFC call chain through VPN → 700 ms.
  • After: CAP service directly exposed via BTP → 310 ms.
  • Outcome: dealer checkout conversion +8 %.

Z-code reduction: 48 000 lines deleted; ATC critical findings –100 %.

Pitfalls & Pro-Tips 

PitfallFix
CDS enum mismatchUse @cds.odata.valuelist for domain values; sync with DDIC check table.
Event duplicatesDe-duplicate by message ID; CAP persists last processed offset.
HANA Cloud memory spikePartition KONV by fiscal year; purge archive years.
Fiori app calls old RFCUse UI5 cache buster; adjust destination to CAP SACF.
Devs fear CAP learning curveScaffold service with yeoman-generator-cap-project—5 min ramp.

Adoption Roadmap 

SprintMilestone
1Enable abapGit, export domain package
2Define CDS & deploy to HANA Cloud
3Build CAP service & Event Mesh subscription
420 % canary traffic via APIM
5Full cut-over; retire old Z-code package

Repeat domain by domain until ECC monolith collapses into modular CAP landscape.

Take-Home Checklist 

  1. Pick a self-contained domain (≤ 5 tables).
  2. Model CDS + deploy to HANA Cloud.
  3. Build CAP OData service; subscribe to Event Mesh.
  4. Canary route 20 % traffic; monitor p95 latency.
  5. Delete Z-code after success—win back predictability.