SAP Clean Core is not a single API or product -- it is a strategic framework and governance model that spans all SAP S/4HANA editions (Cloud Public, Cloud Private, and On-Premise). The framework defines how custom extensions, integrations, and configurations should be built to keep the ERP core standard, upgrade-safe, and cloud-ready. It covers six dimensions: clean processes, clean extensions, clean data, clean integration, clean operations, and clean software stack. This card focuses on the clean extensions dimension. [src4]
| Property | Value |
|---|---|
| Vendor | SAP |
| System | SAP S/4HANA (2025 / 2408) |
| API Surface | OData v2/v4, ABAP Cloud, BTP CAP (Node.js / Java) |
| Framework Version | Clean Core Level Concept (replaces 3-Tier, August 2025) |
| Editions Covered | Cloud Public, Cloud Private, On-Premise |
| Deployment | Cloud / On-Premise / Hybrid |
| API Docs | SAP API Business Hub |
| Status | GA (evolved from 3-Tier to A-D in 2025) |
SAP Clean Core defines multiple extension surfaces, each with different clean core compliance implications. The fundamental principle is: extensions must access SAP business objects only through well-defined, upgrade-stable interfaces. [src3]
| Extension Surface | Technology | Clean Core Level | Best For | Deployment | Upgrade-Safe? | Cloud Public? |
|---|---|---|---|---|---|---|
| Key User Extensibility | Custom Fields & Logic, SAP Build | A | Simple field additions, validations, form adaptations | On-stack | Yes | Yes |
| Developer On-Stack (ABAP Cloud) | ABAP Cloud (restricted language version) | A | Complex business logic using released APIs only | On-stack | Yes | Yes |
| Side-by-Side (BTP CAP) | CAP (Node.js/Java), SAP Build Apps | A | Independent apps, AI/ML, cross-system orchestration | BTP | Yes | Yes |
| Classic ABAP (released BAPIs/RFCs) | BAPIs, IDocs, RFCs, batch jobs | B | Legacy-compatible, stable but not cloud-ready | On-stack | Mostly | No |
| Classic ABAP (unreleased objects) | Internal SAP objects, archiving frameworks | C | Legacy gap-filling, data management | On-stack | Risky | No |
| Modifications / direct table writes | SAP standard modifications, implicit enhancements | D | Never recommended | On-stack | No | No |
Clean Core does not define traditional API rate limits. Instead, the constraints are governance-based: what you are allowed to develop, and what the ATC will permit through transport pipelines. [src5]
| Restriction | ABAP Cloud (Level A) | Classic ABAP (Level B-D) | Notes |
|---|---|---|---|
| Allowed syntax | Restricted subset (no dynpro, no classic reports, no direct DB writes) | Full ABAP syntax | ABAP Cloud enforces at compile time |
| Object access | Released APIs only (SAP API Business Hub / Cloudification Repository) | Any SAP object | ~25,000+ released objects as of 2025 |
| Database access | CDS views and released ABAP SQL only | Direct table reads/writes | No SELECT on SAP tables in ABAP Cloud |
| UI technology | SAP Fiori / SAPUI5 (via RAP) | Classic dynpro, SAP GUI, Web Dynpro | Classic UIs are Level C/D |
| Enhancement technique | BAdIs (released) only | BAdIs, enhancements, modifications, user exits | Only released BAdIs qualify for Level A |
| ATC Check Variant | Purpose | Level A Finding | Level B Finding | Level C Finding | Level D Finding |
|---|---|---|---|---|---|
| CLOUD_READINESS | Primary clean core assessment | No findings | Informational messages | Warnings | Errors (may block transport) |
| S4HANA_READINESS | Legacy ECC pattern detection | N/A | N/A | Warnings | Errors |
| ABAP_CLEAN_CORE_READINESS | Comprehensive (BTP 2605+) | No findings | Informational | Warnings | Errors (blocking) |
| Flow | Use When | Technology | Level | Notes |
|---|---|---|---|---|
| Communication Arrangement | On-stack ABAP Cloud calling external systems | SAP Communication Management | A | Standard for on-stack outbound calls |
| OAuth 2.0 Client Credentials | BTP side-by-side calling S/4HANA APIs | SAP BTP Destination Service | A | Recommended for server-to-server |
| OAuth 2.0 SAML Assertion | BTP extension with user context propagation | SAP BTP + IAS/IPS | A | Preserves user identity across systems |
| Principal Propagation | BTP app needs S/4HANA user authorization | SAP Cloud Connector + BTP | A | Required when on-premise |
| RFC Trust (SM59) | Classic system-to-system communication | RFC Destinations | B | Stable but not cloud-ready |
START -- Organization wants clean core compliant extensions for SAP S/4HANA
|
+-- Which S/4HANA edition?
| +-- Cloud Public Edition
| | +-- Only Level A allowed
| | +-- Key user extension? (custom fields, logic, forms)
| | | +-- YES --> Custom Fields & Logic app, SAP Build Process Automation
| | | +-- NO --> Developer extension needed?
| | | +-- On-stack logic, tight ERP integration --> ABAP Cloud (RAP, released BAdIs)
| | | +-- Independent app, AI/ML, cross-system --> BTP side-by-side (CAP)
| | | +-- Low-code workflow/app --> SAP Build Apps / Process Automation
| |
| +-- Cloud Private Edition or On-Premise
| +-- New development?
| | +-- YES --> Target Level A (ABAP Cloud or BTP)
| | +-- NO --> Existing custom code?
| | +-- Run ATC CLOUD_READINESS check
| | +-- Level A findings? --> Already clean, maintain
| | +-- Level B findings? --> Stable but plan migration to released APIs
| | +-- Level C findings? --> Monitor via Simplification Database, plan remediation
| | +-- Level D findings? --> Remediate immediately (highest risk)
|
+-- What type of extension?
| +-- Simple configuration (fields, validations)
| | --> Key User Extensibility (Level A, no coding)
| +-- Complex business logic, tight ERP coupling
| | --> ABAP Cloud on-stack (Level A) -- use released APIs/BAdIs only
| | --> If released API missing: use wrapper (Level B) + log gap for SAP
| +-- Independent application, UI, or process
| | --> BTP side-by-side with CAP (Level A)
| +-- AI/ML, advanced analytics, cross-system orchestration
| | --> BTP side-by-side (Level A) + SAP AI Core / HANA Cloud
| +-- Legacy interface maintenance
| --> Classify with ATC, plan migration path, target Level A
|
+-- Custom code migration (ECC or classic S/4HANA)?
+-- Step 1: Run Custom Code Migration app against source system
+-- Step 2: Analyze ATC findings by clean core level (A/B/C/D)
+-- Step 3: Prioritize -- eliminate Level D first, then C, then B
+-- Step 4: For each finding: keep + wrap (B) vs. rewrite (A) vs. retire
+-- Step 5: New development in ABAP Cloud only
| Level | Compliance | Technologies | ATC Finding | Upgrade Risk | Cloud Public? | Recommended? |
|---|---|---|---|---|---|---|
| A | Fully compliant | ABAP Cloud, BTP/CAP, SAP Build, Key User Tools | None | None | Yes | Yes -- target for all new development |
| B | Conditionally compliant | BAPIs, IDocs, RFCs, released-but-classic APIs | Informational | Low | No | Acceptable for existing code, plan migration |
| C | Partially compliant | Unreleased SAP objects, archiving (ADK/ILM), TAANA | Warnings | Medium | No | Monitor via SDB, remediate within 12 months |
| D | Non-compliant | Modifications, direct table writes, implicit enhancements, NoAPI | Errors (blocking) | High | No | Eliminate immediately |
| Old Model | New Model | What Changed |
|---|---|---|
| Tier 1 (ABAP Cloud on-stack + BTP side-by-side) | Level A | Same scope, renamed for clarity |
| Tier 2 (wrapper for unreleased APIs) | Level B | Downgraded -- wrappers are no longer "clean" |
| Tier 3 (classic ABAP) | Level C + D | Split into two: C (risky but manageable) vs D (prohibited) |
| Dimension | Key User (on-stack) | Developer (on-stack) | Side-by-Side (BTP) |
|---|---|---|---|
| Skill required | Business analyst | ABAP developer | Full-stack developer (Node.js/Java) |
| Tools | Custom Fields & Logic app, SAP Build | ABAP Development Tools (Eclipse), RAP | SAP Business Application Studio, CAP |
| Language | No-code / low-code | ABAP Cloud (restricted) | Node.js, Java, Python |
| Deployment | S/4HANA tenant | S/4HANA tenant | BTP Cloud Foundry or Kyma |
| Data access | Predefined extension points | Released APIs, CDS views | S/4HANA APIs via Destination Service |
| Lifecycle | Managed by S/4HANA upgrades | Managed by developer, ATC-validated | Independent lifecycle |
| Best for | Custom fields, simple validations, UI adaptations | Complex business logic, custom entities, reports | Independent apps, AI/ML, cross-system processes |
| Clean Core Level | A | A (if released APIs only) | A |
Run the ABAP Test Cockpit with the CLOUD_READINESS check variant to classify all custom code objects by clean core level. [src5]
" In SAP GUI: transaction ATC or SE80 > ATC
" Or via BTP ABAP Environment for remote analysis:
" 1. Configure central ATC on BTP (recommended by SAP)
" 2. Connect source S/4HANA system via RFC
" 3. Run check variant CLOUD_READINESS against Z* / Y* namespaces
" 4. Export findings report (Excel or ALV)
Verify: ATC results show findings categorized as Informational (Level B), Warning (Level C), or Error (Level D). No findings = Level A compliant.
Create a new development object using ABAP Cloud language version. Only released APIs are accessible. [src1]
" In ABAP Development Tools (Eclipse):
" 1. Create a new ABAP Package with language version "ABAP for Cloud Development"
" 2. All objects in this package are restricted to ABAP Cloud syntax
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Custom Sales Order View'
define view entity ZI_SalesOrderCustom
as select from I_SalesOrder " <-- released CDS view (Level A)
{
key SalesOrder,
SalesOrganization,
SoldToParty,
TotalNetAmount,
TransactionCurrency
}
where SalesOrganization = '1000'
Verify: ATC run on the new object shows zero findings. Object deploys without transport errors.
When a released API does not exist for your use case, create a wrapper in Standard ABAP and release it for ABAP Cloud consumption. Plan to remove the wrapper once SAP releases the official API. [src1]
" Step 1: Create wrapper class in Standard ABAP (language version: Standard)
CLASS zcl_wrapper_example DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS get_material_data
IMPORTING iv_matnr TYPE matnr
RETURNING VALUE(rs_data) TYPE mara.
ENDCLASS.
CLASS zcl_wrapper_example IMPLEMENTATION.
METHOD get_material_data.
SELECT SINGLE * FROM mara INTO rs_data WHERE matnr = iv_matnr.
ENDMETHOD.
ENDCLASS.
" Step 2: Release wrapper class for ABAP Cloud: Properties > API State > Released
" Step 3: In ABAP Cloud code, consume the released wrapper
" Step 4: When SAP releases the API, replace wrapper with released API
Verify: ATC on the ABAP Cloud consumer shows Informational finding (Level B).
Create an independent application on SAP BTP that connects to S/4HANA via APIs. [src3, src6]
# Scaffold a CAP project
npm init -y
npm add @sap/cds @sap/cds-dk
npx cds init my-extension --add hana,approuter
# Import S/4HANA OData service definition
cd my-extension
npx cds import API_SALES_ORDER_SRV.edmx --as external
# Deploy to Cloud Foundry
cf login -a https://api.cf.<region>.hana.ondemand.com
npx cds build --production
cf push
Verify: cf apps shows the application running. API returns data from S/4HANA.
# Input: GitHub Cloudification Repository JSON
# Output: List of released objects matching a search term
import requests # requests==2.31.0
CLOUDIFICATION_REPO_URL = (
"https://raw.githubusercontent.com/SAP/abap-atc-cr-cv-s4hc/"
"main/src/objectReleaseInfo_s4hc2408.json"
)
def search_released_objects(search_term: str, max_results: int = 20):
resp = requests.get(CLOUDIFICATION_REPO_URL, timeout=30)
resp.raise_for_status()
data = resp.json()
results = []
term_lower = search_term.lower()
for obj in data.get("objectReleaseInfo", []):
obj_name = obj.get("objectName", "").lower()
if term_lower in obj_name:
results.append({
"name": obj.get("objectName"),
"type": obj.get("objectType"),
"release_state": obj.get("releaseState"),
})
if len(results) >= max_results:
break
return results
released = search_released_objects("salesorder")
for obj in released:
print(f" {obj['type']:10s} {obj['name']:40s} [{obj['release_state']}]")
" Input: Object name (class, CDS view, etc.)
" Output: Release state (released / not released / deprecated)
" Method 1: Use XCO library (available in ABAP Cloud)
DATA(lo_class) = xco_cp_abap=>class( 'CL_SOME_SAP_CLASS' ).
DATA(lv_release_state) = lo_class->content( )->get_release_state( ).
" Returns: if_xco_ar_release_state=>co_released
" Method 2: Use Cloudification Repository Viewer (Fiori app)
" App ID: F5670 - ABAP Cloud Readiness
" Method 3: ATC Check (most comprehensive)
" Transaction ATC > Run with CLOUD_READINESS variant
| Extension Pattern | Old Model | New Level | Migration Path | Effort |
|---|---|---|---|---|
| Custom Fiori app using released OData | Tier 1 | A | None needed | - |
| CAP app on BTP calling S/4 APIs | Tier 1 | A | None needed | - |
| Key user custom fields via Custom Fields app | Tier 1 | A | None needed | - |
| BAPI wrapper in Standard ABAP, released for Cloud | Tier 2 | B | Replace with released API when available | Low-Medium |
| Classic report (WRITE statement) on Z-table | Tier 3 | C | Rewrite as RAP-based Fiori app | High |
| User exit / customer exit | Tier 3 | C-D | Replace with released BAdI | Medium-High |
| SAP standard modification (SMOD/CMOD) | Tier 3 | D | Eliminate, use BAdI or BTP extension | High |
| Direct MODIFY on SAP table | Tier 3 | D | Eliminate, use released API | Critical |
| Implicit enhancement point | Tier 3 | D | Eliminate, use released BAdI | High |
| ATC Message | Level | Meaning | Resolution |
|---|---|---|---|
| Use of unreleased SAP object | C | Code accesses an internal SAP object not in Cloudification Repository | Replace with released equivalent or create wrapper (Level B) |
| Use of classic ABAP statement | C | Code uses dynpro, WRITE, CALL SCREEN, etc. | Rewrite using RAP/Fiori patterns |
| Direct access to SAP database table | C-D | SELECT/MODIFY on SAP tables (VBAK, MARA, etc.) | Use released CDS views or APIs |
| Modification of SAP standard object | D | SMOD/CMOD modification, implicit enhancement | Eliminate and use BAdI/BTP extension |
| Use of NoAPI object | D | Object explicitly flagged by SAP as "do not use" | Must be removed -- no workaround |
| Obsolete ABAP statement | B-C | Code uses obsolete syntax (MOVE, COMPUTE, etc.) | Replace with modern ABAP syntax |
Run ATC early in project planning, not during build phase. [src5]Maintain a wrapper registry with SAP Influence request numbers; set quarterly review cadence. [src1]Implement health check endpoints; set up BTP Alert Notification Service for destination failures. [src3]Standardize on SAP-delivered CLOUD_READINESS variant across all systems. [src5]Test key user extensions in sandbox system before production upgrade. [src6]" BAD -- creating hundreds of wrappers to make classic code "technically" compliant
" This creates unmanageable technical debt and a shadow API layer
CLASS zcl_wrap_mara DEFINITION PUBLIC CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS get IMPORTING iv TYPE matnr RETURNING VALUE(rs) TYPE mara.
ENDCLASS.
CLASS zcl_wrap_bseg DEFINITION PUBLIC CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS get IMPORTING iv TYPE belnr_d RETURNING VALUE(rs) TYPE bseg.
ENDCLASS.
" ... 200 more wrappers ...
" GOOD -- decision tree for each unreleased object:
" 1. Does a released API exist? --> Use it (Level A)
" 2. Is the functionality still needed? --> Maybe retire the custom code
" 3. Can it be rebuilt as a BTP extension? --> Side-by-side (Level A)
" 4. No alternative exists? --> Create ONE wrapper, log SAP Influence request,
" set review date, and document in wrapper registry
" BAD -- developer creates a classic report because "that's how we always did it"
REPORT zsd_order_list.
SELECT * FROM vbak INTO TABLE @DATA(lt_orders)
WHERE erdat >= @sy-datum - 30.
LOOP AT lt_orders INTO DATA(ls_order).
WRITE: / ls_order-vbeln, ls_order-erdat, ls_order-netwr.
ENDLOOP.
" GOOD -- same requirement, Level A compliant
" 1. Create a CDS view consuming released I_SalesOrder
" 2. Expose via RAP service binding (OData V4)
" 3. Build Fiori Elements list report (zero UI code)
@EndUserText.label: 'Recent Sales Orders'
define view entity ZC_RecentSalesOrders
as select from I_SalesOrder
{
key SalesOrder,
CreationDate,
TotalNetAmount,
TransactionCurrency
}
where CreationDate >= $session.system_date - 30
Use the extension decision tree: key user > ABAP Cloud > BTP side-by-side. [src4]Run ATC with CLOUD_READINESS variant on all Z*/Y* objects as the first project activity. [src5]Check each BAPI against the Cloudification Repository. [src7]Include BTP licensing in the business case. Use SAP Discovery Center to estimate credit consumption. [src3]Subscribe to SDB notifications for all Level C objects in your landscape. [src2]If the extension requires ABAP code, external API calls, or complex data models, use developer extensibility or BTP. [src6]" Check ATC findings for a specific package
" Transaction: ATC
" 1. Create/select check variant: CLOUD_READINESS
" 2. Object scope: Package = Z_MY_PACKAGE (including subpackages)
" 3. Execute > Review findings by priority (Error > Warning > Info)
" Check released status of a specific object
" Transaction: SE80 or ADT (Eclipse)
" Navigate to object > Properties > API State
" Released = Level A compatible
" Check Clean Core Dashboard metrics
" SAP for Me > Clean Core Dashboard (S/4HANA Cloud Private Edition)
" Cloudification Repository (programmatic check)
" GitHub: https://github.com/SAP/abap-atc-cr-cv-s4hc
# Check Cloudification Repository for a specific object (command line)
curl -s "https://raw.githubusercontent.com/SAP/abap-atc-cr-cv-s4hc/main/src/objectReleaseInfo_s4hc2408.json" \
| python3 -c "
import json, sys
data = json.load(sys.stdin)
term = 'salesorder'
for obj in data.get('objectReleaseInfo', []):
if term.lower() in obj.get('objectName', '').lower():
print(f\"{obj['objectType']:10s} {obj['objectName']:40s} [{obj['releaseState']}]\")
"
| Framework Version | Date | Status | Key Changes | Migration Notes |
|---|---|---|---|---|
| A-D Clean Core Levels | 2025-08 | Current | Replaced 3-tier model; 4 levels with ATC-based governance | Tier 2 reclassified as Level B; Tier 3 split into C + D |
| 3-Tier Extensibility Model | 2022-2025 | Superseded | Tier 1 (clean), Tier 2 (wrapper), Tier 3 (classic) | Tier 1 = Level A; Tier 2 = Level B; Tier 3 = Level C/D |
| ABAP Cloud (introduction) | 2020 | GA | Restricted ABAP language version for cloud development | Required for all Level A on-stack extensions |
| RAP (RESTful ABAP Programming) | 2020 | GA | Application framework for ABAP Cloud | Standard pattern for Level A transactional apps |
| SAP BTP Extension Suite | 2019 | GA | Side-by-side extension platform | Required for Level A side-by-side extensions |
SAP does not deprecate clean core levels -- they are cumulative and backward-compatible. SAP commits to a 2-year deprecation notice for any released API that will be removed. The Cloudification Repository on GitHub is updated with each S/4HANA release. [src1, src7]
| Use When | Don't Use When | Use Instead |
|---|---|---|
| Planning S/4HANA cloud migration and need to assess custom code | Already on S/4HANA Cloud Public with no custom ABAP | Key user extensibility tools directly |
| Building new extensions for S/4HANA (any edition) | Working with SAP ECC (pre-S/4HANA) | Migrate to S/4HANA first, then apply clean core |
| Need to classify existing custom code by upgrade risk | Need specific API rate limits and endpoints | SAP S/4HANA OData API Capabilities |
| Evaluating BTP vs on-stack extension architecture | Need BAPI/RFC technical details | SAP BAPI/RFC Integration |
| Setting up ATC governance and CI/CD transport controls | Need SAP Integration Suite capabilities | SAP Integration Suite Capabilities |
| Deciding between key user, developer, and side-by-side | Need authentication setup details | SAP Authentication Methods |