Enhancements Part 9: Performance and Safety in Enhancements
Write enhancement code that never harms the standard process: no COMMIT/ROLLBACK, no dialogs in background, correct messages, buffered reads instead of SELECTs per item, guard conditions, exception handling, and how to test and monitor enhancements (ST05, SAT, ST22).
Explanation
📌 KEY POINTS
✅ Enhancement code runs inside SAP's LUW: never COMMIT WORK, ROLLBACK WORK or CALL TRANSACTION that commits.
✅ Code in exits and BAdIs may run per item, per document and in background — design for volume.
✅ Messages must fit the context: type E at the right place (check exits), no popups in background or update task.
⚠️ One SELECT in an item-level exit can become 500,000 SELECTs in a mass run — buffer.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Parts 1–8 were about choosing and implementing enhancements. This lesson makes sure they don't break or slow down standard processes.
━━━━━━━━━━━━━━━━━━━━
▶ 1. TRANSACTION CONSISTENCY
- SAP saves the document at the end of its own LUW. A COMMIT in your code writes half-finished data or breaks the update.
- Don't call BAPIs that commit, CALL TRANSACTION, or SUBMIT AND RETURN with commits inside save exits.
- For additional database changes: use update function modules IN UPDATE TASK or PERFORM … ON COMMIT so they are saved with SAP's commit.
━━━━━━━━━━━━━━━━━━━━
▶ 2. MESSAGES AND DIALOGS
- Error messages (type E) belong in validation exits (e.g. USEREXIT_SAVE_DOCUMENT_PREPARE, check BAdI methods). In other exits they can terminate processing unexpectedly.
- No POPUP_TO_CONFIRM, no screens when sy-batch = 'X' or in update task.
- In BAPIs/IDocs there is no user — messages must be returned, not displayed.
━━━━━━━━━━━━━━━━━━━━
▶ 3. PERFORMANCE
- Avoid SELECT inside item loops; read once per document (or buffer in a static/class attribute keyed by document).
- Use SELECT SINGLE with full key or buffered tables; check with ST05 and SAT.
- Guard conditions first: IF vbak-auart <> 'ZOR'. RETURN. ENDIF. → the enhancement does nothing for other cases.
- Clear buffers when the document changes (keyed buffer, not "first call only").
━━━━━━━━━━━━━━━━━━━━
▶ 4. ROBUSTNESS
- Catch exceptions from your classes; a dump in an exit stops the whole transaction (ST22).
- Don't rely on SAP global variables that are not documented for that exit.
- Initialise your own global variables — exits run many times in one session.
━━━━━━━━━━━━━━━━━━━━
▶ 5. TESTING AND MONITORING
- Test all paths: dialog, background (mass), BAPI, IDoc.
- Measure with a realistic volume; compare runtime with and without the enhancement.
- After go-live, check ST22 and SM13 (update errors) regularly.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Review an existing item-level exit: count SELECTs with ST05 on a 100-item order.
- Introduce a keyed buffer as in the code example and re-measure.
- Search your enhancements for COMMIT WORK (SE80 code scanner / CODE_SCANNER).
✅ CHECKPOINT: your enhancements respect the LUW, give correct messages and scale with volume.
Code example
* ===== Buffered read helper used by item-level enhancements =====CLASS zcl_mat_buffer DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS get_mat_group IMPORTING iv_matnr TYPE matnr RETURNING VALUE(rv_matkl) TYPE matkl. PRIVATE SECTION. TYPES: BEGIN OF ty_mat, matnr TYPE matnr, matkl TYPE matkl, END OF ty_mat. CLASS-DATA gt_mat TYPE HASHED TABLE OF ty_mat WITH UNIQUE KEY matnr.ENDCLASS. CLASS zcl_mat_buffer IMPLEMENTATION. METHOD get_mat_group. DATA ls_mat TYPE ty_mat. READ TABLE gt_mat INTO ls_mat WITH TABLE KEY matnr = iv_matnr. IF sy-subrc <> 0. " read DB only once per material ls_mat-matnr = iv_matnr. SELECT SINGLE matkl FROM mara INTO ls_mat-matkl WHERE matnr = iv_matnr. INSERT ls_mat INTO TABLE gt_mat. ENDIF. rv_matkl = ls_mat-matkl. ENDMETHOD.ENDCLASS. * ===== Item-level enhancement: guard first, buffer, no COMMIT =====ENHANCEMENT 1 zei_item_matkl_check. "active version DATA lv_matkl TYPE matkl. IF vbak-auart = 'ZOR'. " guard: only relevant order type lv_matkl = zcl_mat_buffer=>get_mat_group( vbap-matnr ). IF lv_matkl = 'Z_RESTRICT' AND sy-batch = abap_false. MESSAGE w010(zsd) WITH vbap-matnr. " warning online, no popup ENDIF. ENDIF.* NEVER here: COMMIT WORK / ROLLBACK WORK / CALL TRANSACTION / POPUP in backgroundENDENHANCEMENT. * ===== Extra DB change saved together with SAP's document =====* CALL FUNCTION 'Z_SAVE_ORDER_LOG' IN UPDATE TASK* EXPORTING is_log = ls_log. " executed at SAP's COMMIT WORKReal project scenario
A billing exit read the customer master (KNVV) and a Z pricing table for every item. Monthly billing of 400,000 items took 9 hours instead of 2, and the job overlapped with the morning shift.
ST05 showed 800,000 identical SELECTs. The team added a guard condition for the relevant billing types and a keyed buffer class; runtime dropped to 2 hours 15 minutes. A code review also found a COMMIT WORK in another exit, which was replaced by an update function module.
Common mistakes
- COMMIT WORK or BAPI with commit inside exits.
- Popups or error messages in background and interfaces.
- SELECT per item without buffering.
- No guard conditions — code runs for every document.
- Global variables not initialised between documents.
Best practices
- Respect SAP's LUW; use update task for extra writes.
- Guard conditions at the top.
- Buffer reads with keyed tables.
- Messages appropriate to exit type and processing mode.
- Test with volume and all paths; monitor ST22/SM13.
Interview angle
Questions: "What must you never do in a user exit or BAdI?", "How do you make enhancements performant?", "How do you save extra data from an exit?"
Strong answer: no COMMIT/ROLLBACK/CALL TRANSACTION inside SAP's LUW; extra data via update FM IN UPDATE TASK or PERFORM ON COMMIT; no dialogs in background/BAPI; error messages only in validation exits; guard conditions, buffered reads, no SELECT per item; test all paths with volume; monitor ST22/SM13.
Practice this lesson
Quick check
1. A pricing enhancement needs customer data for every item. What is the best approach?
2. An enhancement must store an extra log record together with the SAP document. How should it be written?
3. Which statement must never appear in a user exit or BAdI running during document save?
Interview questions
1. A colleague implemented a CMOD exit that directly modifies the VBAK table inside USEREXIT_SAVE_DOCUMENT. Explain why this is dangerous and describe the correct approach.
Answer it in your own words first, then compare.
2. Your CMOD enhancement includes complex database queries and BAPI calls. You're experiencing performance issues. How would you debug and optimize the exit performance? What are anti-patterns to avoid?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- Enhancements Part 1: SAP Enhancement Techniques Overview
- Enhancements Part 10: Enhancements in S/4HANA and Clean Core
- Enhancements Part 2: The Enhancement Framework Overview
- Enhancements Part 3: Implicit vs Explicit Enhancement Points
- Enhancements Part 4: Finding Enhancements Using Debugging
- Enhancements Part 5: Implementing Explicit Enhancement Points and Sections
- Enhancements Part 6: Enhancement Spots and Implementations
- Enhancements Part 7: Implicit Enhancements — Power and Risk