โ† Back to Clean Core Architecture Hub
CLEAN CORE ARCHITECTURAL GUIDE #15

SAP RAP Draft Architecture & Concurrency Lock Management

Author: Andrea Antonio Perrelli Scope: SAP S/4HANA Cloud (Public & Private) & BTP ABAP Environment Framework: RAP Transactional Engine (Draft Lifecycle & Enqueue)
Enterprise Architecture Imperative: In stateful Fiori applications, users require auto-save and draft capabilities. In the SAP RESTful Application Programming Model (RAP), draft handling separates uncommitted working state (in draft staging tables) from verified active state (in primary ERP tables). Proper draft architecture prevents lock stagnation, database bloating, and phantom updates.
Limited Time Deal

Master S/4HANA Clean Core Architecture & RAP

Get the Complete SAP Enterprise Architecture Suite: 40 Retina architecture diagrams, 61 production-grade code listings, and decision frameworks. Use code FLASH80 at checkout for 80% OFF.

1. The 3-Layer Storage Architecture of Draft

When an entity is declared with draft; in its Behavior Definition (BDEF), the SAP RAP engine coordinates three storage tiers:

Storage Tier Physical Persistence Data Lifecycle & Scope Lock Mechanism
Active Persistence Standard ERP Table (e.g., ZSD_ORDER_A) Authoritative, fully validated, committed transactional records. Optimistic ETag check on edit.
Draft Persistence Draft Staging Table (e.g., ZSD_ORDER_D) Temporary working state; allows incomplete, unvalidated inputs. Exclusive enqueue lock held by active editing user.
Transactional Buffer Application Server Memory (Internal Tables) In-flight modifications during the current interaction phase. Process memory boundaries.

2. Draft Lifecycle Operations

The RAP framework provides built-in draft actions that govern transition between active and draft states:

3. Optimistic Concurrency & Total ETag

To prevent the "Lost Update" problem where User B overwrites User A's uncommitted changes, RAP mandates two levels of ETag definitions:

managed implementation in class zbp_r_order_root unique;
strict ( 2 );
with draft;

define behavior for ZR_ORDER_ROOT alias Order
persistent table zsd_order_a
draft table zsd_order_d
lock master total etag LastChangedAt  // Checks concurrent edits on active record
etag master LocalLastChangedAt        // Checks concurrent edits on draft buffer
{
  draft action Edit;
  draft action Activate optimized;
  draft action Discard;
  draft action Resume;
  draft determine action Prepare;

  field ( readonly, numbering : managed ) OrderUUID;
  field ( readonly ) OrderID, CreatedAt, CreatedBy, LastChangedAt;

  create;
  update;
  delete;
}

4. Enterprise Housekeeping: The Draft Accumulation Problem

In high-volume systems, users frequently abandon browser sessions or close laptop lids without clicking "Save" or "Cancel". This creates two major problems:

  1. Orphan Locks: The active record remains locked with the message "Object is locked by user X in another draft session".
  2. Draft Table Bloat: Thousands of abandoned draft rows accumulate in Z*_D tables, slowing down indexing and CDS joins.
Strict Rule: Never execute raw SQL DELETE FROM zsd_order_d! Directly deleting database rows bypasses the enqueue server, leaving phantom lock entries in transaction SM12. Always trigger EML EXECUTE Discard.

5. Production EML Cleanup Implementation

The following is the contract-compliant method for discarding stale draft records programmatically:

" =====================================================================
" Method: Purge Stale Drafts via EML
" Language Version: ABAP Cloud (Language Version 5)
" =====================================================================
METHOD purge_expired_drafts.
  DATA(lv_cutoff) = utclong_add( val = utclong_current( ) hour = -72 ).

  " 1. Query expired drafts via administrative metadata
  SELECT OrderUUID
    FROM zsd_order_d
    WHERE draftlastchangedatetime < @lv_cutoff
    INTO TABLE @DATA(lt_expired).

  CHECK lt_expired IS NOT INITIAL.

  " 2. Construct Discard EML payload
  DATA: lt_discard TYPE TABLE FOR ACTION IMPORT zr_order_root~Discard.
  lt_discard = VALUE #(
    FOR ls IN lt_expired (
      %tky-%is_draft  = if_abap_behv=>mk-on
      %tky-OrderUUID  = ls-OrderUUID
    )
  ).

  " 3. Execute framework discard action
  MODIFY ENTITIES OF zr_order_root
    ENTITY Order
    EXECUTE Discard FROM lt_discard
    FAILED DATA(lt_failed)
    REPORTED DATA(lt_reported).

  " 4. Release locks
  COMMIT ENTITIES.
ENDMETHOD.

Recommended Clean Core Developer Tools

Explore free client-side interactive utilities to accelerate your S/4HANA migration:

๐Ÿงน RAP Draft Cleaner Daemon โšก RAP BDEF & EML Syntax โš–๏ธ RAP Architecture Decision ๐Ÿงญ Decision Wizard & ADR

Accelerate Your SAP Transformation

Get complete architectures, downloadable code listings, and decision frameworks in the official handbooks.