Lesson 1 of 5
Stable dependencies: build only on released contracts
11 min
Listen to this lesson
Contoso Motor Co. now runs three extensions on SAP BTP next to its converted SAP S/4HANA system: the fleet order status app, the event-driven fleet order notifier, and a warranty app that is still on the drawing board. Each one will outlive several S/4HANA feature pack stacks and at least one upgrade. Whether those upgrades are routine or a crisis is decided long before they happen, by one design question: what exactly does the extension depend on, and has SAP promised that it will stay stable?
| Level | SAP's description (2025) | Typical technique | Upgrade risk |
|---|---|---|---|
| A | Fully compliant: only publicly released, stable SAP interfaces with formal stability contracts | Side-by-side on SAP BTP or on-stack ABAP Cloud, using released APIs and events | Lowest |
| B | Compliant: Level A plus SAP's classic APIs, which are documented and generally upgrade-stable | Classic APIs where no released successor exists yet | Low |
| C | Partially compliant: accesses SAP internal objects | Reading internal tables or calling unreleased function modules | Needs proactive upgrade planning |
| D | Not recommended: modifications, write access to SAP tables, implicit enhancements | Anything that changes or writes into SAP's own objects | Highest; technical debt |
What counts as a stable dependency
For a side-by-side extension, the stable surface of SAP S/4HANA is small and well documented: released APIs (OData and SOAP services listed in the SAP Business Accelerator Hub with a released state), released business events, and, for on-stack code, released ABAP objects used through ABAP Cloud. These carry SAP's stability contract: they are versioned, and when SAP replaces one, it deprecates the old version and points to a successor rather than changing it silently. Everything else (a database table read through a custom service, an unreleased function module called by RFC, a screen scraped by a bot) works until the day it does not.
Stability is not only about S/4HANA. The extension also depends on BTP services, on the runtime (a Node.js or Java version on Cloud Foundry), on open-source libraries and on other teams' APIs. An expert design lists all of them, not only the SAP ones.
The dependency register
Contoso's architecture rule is short: every extension keeps a dependency register, reviewed at each architecture review and each upgrade. For each dependency it records the exact name and version, its release state, the clean core level it implies, the owner, and the tests that would catch a breaking change. The register turns a vague worry ("will the upgrade break the warranty app?") into a list that Priya's team can test against.
| Dependency | Version / state | Level | Covered by |
|---|---|---|---|
| Sales Order OData API (released) | Current version, released | A | Contract tests in cmc-ext-test against CMQ |
| SalesOrder Created / Changed events | v1, released | A | Event contract tests with the AsyncAPI schema |
| Core return agreements RAP business object and event | Contoso v1, owned by Kenji's team | A (ABAP Cloud) | ABAP Unit plus event contract tests |
| Read of an internal pricing table via custom RFC | Unreleased | C | Flagged: replace before the next upgrade |
| Node.js runtime | Pinned major version | n/a | Pipeline build; runtime deprecation notices tracked |
An extract of Contoso's dependency register (illustrative).
- Is there a released API or event that provides what the extension needs?Yes → use it (Level A) · No → continue
- Is there a classic, documented API that is generally upgrade-stable?Yes → use it, record it as Level B and watch for a released successor · No → continue
- Can the need be met by a custom RAP business object or event in ABAP Cloud?Yes → build the contract yourself on released objects · No → continue
- Is internal access truly unavoidable?Yes → Level C: isolate it behind one adapter, register it, plan its replacement · No → redesign
Isolate what you cannot avoid
Sometimes a Level C dependency is the only way to meet a deadline. The expert move is not to pretend otherwise but to contain it: put the access behind one adapter in the code (one module, one service), give it its own contract tests, register it, and set a date to replace it. When the upgrade comes, the blast radius is one adapter, not the whole app. Version your own contracts the same way: Contoso's fleet order notifier publishes a portal update API at v1; a breaking change becomes v2, and v1 stays until the portal has moved.
What would you do?
The warranty app needs the standard cost of an alternator at the time of sale. A developer finds an internal table that has it and proposes a custom RFC that reads it directly. No released API is known. What should the architect do?
- Upgrade safety is decided by dependencies: released APIs and events, released ABAP objects (Level A) first.
- Clean core levels run from A (released contracts) to D (modifications and writes to SAP tables).
- List every dependency: SAP contracts, BTP services, runtime, libraries and internal APIs.
- Keep a dependency register with version, state, level, owner and covering tests.
- Contain unavoidable Level C access behind one adapter with tests and a replacement date.
Check your understanding · not graded
Lesson check
1. Which clean core level uses only publicly released, stable SAP interfaces?
2. An extension writes directly into an SAP standard table. Which level is that?
3. What should happen when SAP deprecates a released API the app uses?
4. How should an unavoidable Level C dependency be handled?