User Exits Part 2: User Exits vs Customer Exits vs BAdIs — When to Migrate
Compare user exits, customer exits (SMOD/CMOD) and BAdIs by interface, number of implementations, testability and upgrade safety, and decide when existing user-exit logic should stay and when it should move to a BAdI or class-based design.
Explanation
📌 KEY POINTS
✅ User exits: FORMs with full access to global data; customer exits: function modules with fixed parameters; BAdIs: interfaces with classes, filters and multiple implementations.
✅ Migration is worth it when an exit is overloaded, hard to test, shared by many teams or blocks clean-core goals.
✅ Often the best first step is refactoring: keep the exit as entry point and move the logic into classes.
⚠️ Moving logic to a BAdI that runs at a different time or with less data can change behaviour — compare carefully.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 1 introduced user exits. Before diving into specific includes, compare the technologies — you will meet all three.
━━━━━━━━━━━━━━━━━━━━
▶ 1. CUSTOMER EXITS IN BRIEF
- SAP code: CALL CUSTOMER-FUNCTION '001' → FM EXIT_SAPMV45A_001 (example pattern).
- SMOD: shows enhancements and components (function exits, screen exits, menu exits).
- CMOD: your project; code goes into the ZX… include inside the exit FM; activate the project.
- Only one project can use an enhancement.
━━━━━━━━━━━━━━━━━━━━
▶ 2. COMPARISON
- Data access: user exit — all globals; customer exit — parameters only; BAdI — parameters/objects only.
- Implementations: user exit — one code block; customer exit — one project; BAdI — one or many, with filters.
- Testability: user exit — hard; customer exit — medium; BAdI — good (classes).
- Upgrade: all stable, BAdIs cleanest; user exits need an access key.
- S/4HANA: all three still exist on-premise; released BAdIs are the clean-core option.
━━━━━━━━━━━━━━━━━━━━
▶ 3. WHEN TO KEEP A USER EXIT
- SAP offers no BAdI at that point (common in SD save logic).
- Logic is small, documented and stable.
━━━━━━━━━━━━━━━━━━━━
▶ 4. WHEN TO MIGRATE OR REFACTOR
- The exit contains hundreds of lines from several projects.
- A released BAdI for the same purpose exists (check in S/4HANA).
- Multiple countries need different logic (filters would help).
- Business wants unit tests or reuse from Fiori/OData.
━━━━━━━━━━━━━━━━━━━━
▶ 5. HOW TO MIGRATE SAFELY
- Inventory what the exit does (per requirement).
- Check timing and data of the target BAdI (debug both).
- Move logic into classes first, still called from the exit.
- Switch the call to the BAdI implementation; remove it from the exit in the same transport.
- Regression test dialog, BAPI and IDoc paths.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- SMOD: display enhancement V45A0002 and its components.
- Compare MV45AFZZ USEREXIT_SAVE_DOCUMENT_PREPARE with an available sales BAdI in your release (timing, parameters).
- Write a migration decision for one exit using the criteria above.
✅ CHECKPOINT: you can compare the three technologies and decide whether to keep, refactor or migrate an exit.
Code example
* ===== Step 3 of a migration: refactor first, entry point unchanged =====* Before: 250 lines directly in the FORM* After: FORM calls a class; logic becomes testable and reusable FORM userexit_save_document_prepare. DATA: lt_items TYPE zcl_so_rules=>tt_items, ls_item TYPE zcl_so_rules=>ty_item, ls_xvbap TYPE vbapvb, lt_messages TYPE bapiret2_t, ls_message TYPE bapiret2. CHECK t180-trtyp <> 'A'. * Map SAP globals to a clean input (only what the rule needs) LOOP AT xvbap INTO ls_xvbap WHERE updkz <> 'D'. ls_item-posnr = ls_xvbap-posnr. ls_item-matnr = ls_xvbap-matnr. ls_item-kwmeng = ls_xvbap-kwmeng. APPEND ls_item TO lt_items. ENDLOOP. zcl_so_rules=>validate( EXPORTING is_header = vbak it_items = lt_items IMPORTING et_messages = lt_messages ). READ TABLE lt_messages INTO ls_message WITH KEY type = 'E'. IF sy-subrc = 0. MESSAGE ID ls_message-id TYPE 'E' NUMBER ls_message-number WITH ls_message-message_v1 ls_message-message_v2. ENDIF.ENDFORM. * ===== Customer exit for comparison (code in ZX include of EXIT_... FM) =====* INCLUDE ZXVVAU05. " example name - check the FM in SMOD/SE37* IF i_vbak-auart = 'ZOR'. " only parameters are visible* ...* ENDIF. * ===== Later: same class called from a BAdI implementation =====* METHOD <badi_interface>~check.* zcl_so_rules=>validate( ... ). " no logic duplication* ENDMETHOD.Real project scenario
MV45AFZZ in a global template had grown to 3,000 lines from seven projects, and every change needed a full SD regression test. The team did not migrate everything at once: they moved each requirement into a class, called from the same exit, with unit tests.
When the company moved to S/4HANA, five of the classes were connected to released sales BAdIs without rewriting the logic; the rest stayed in the user exit with documented reasons.
Common mistakes
- Big-bang migration of all exits.
- Assuming a BAdI runs at the same time with the same data.
- Duplicating logic in exit and BAdI during migration.
- Forgetting to activate the CMOD project.
- No regression tests for BAPI/IDoc paths.
Best practices
- Refactor logic into classes first.
- Compare timing and data before switching technology.
- Move and remove in the same transport.
- Keep a register of exits, owners and requirements.
- Prefer released BAdIs where they exist in S/4HANA.
Interview angle
Questions: "User exit vs customer exit vs BAdI?", "Would you migrate user exits to BAdIs?", "How do you implement a customer exit?"
Strong answer: user exits are FORMs with global access, customer exits are EXIT_ FMs via CALL CUSTOMER-FUNCTION implemented in ZX includes and activated in CMOD, BAdIs are OO with filters and multiple implementations; migrate when overloaded or when released BAdIs exist; refactor to classes first, check timing/data, test all paths.
Practice this lesson
Quick check
1. What is a safe first step when modernising a 2,000-line MV45AFZZ?
2. Preferred alternative in S/4HANA is:
3. What is a good modernization pattern for a large legacy user exit?
Interview questions
1. How do you make a legacy user exit maintainable?
Answer it in your own words first, then compare.
2. How would you handle user exits during S/4HANA conversion?
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
- User Exits Part 1: What SD User Exits Are and How They Work
- User Exits Part 3: Finding User Exits in Real Transactions
- User Exits Part 4: MV45AFZZ — Sales Order Exits and Save Logic
- User Exits Part 5: MV50AFZ1 — Delivery User Exit Patterns
- User Exits Part 6: RV60AFZZ — Billing User Exit Patterns
- User Exits Part 7: Safe Coding Rules Inside User Exits
- User Exits Part 8: Performance Risks in User Exits