How do you find unused custom code in SAP ECC before an S/4HANA migration?

Developer memory says everything is used. The call monitor says otherwise. The migration should believe the system.

By Chris Benson — 30 years in SAP SD6 min read

The short answer

You find unused custom code in SAP ECC by combining three kinds of evidence from the live system rather than asking developers what they remember: runtime usage data from SAP's ABAP Call Monitor (SCMON, aggregated in SUSG) or the older Usage and Procedure Logging (UPL), which record which Z-programs, function modules, methods, and enhancement implementations actually executed over a representative period; a static where-used analysis that shows which objects are referenced by anything that itself runs; and the business rule each object implements, read from its source, so that a rarely executed object can still be judged on whether the rule it enforces is one the business needs in S/4HANA. Objects with no runtime hits across a full business cycle, no active callers, and a rule that S/4HANA delivers as standard are retirement candidates; objects with hits belong in the fit-to-standard workshop with their execution frequency attached. On a reference estate, a live ECC system used to validate this method rather than a specific customer's result, roughly 44% of 356 inventoried objects were assessed as retirable through this chain; a customer's numbers come from their own system.

Why 'is this still used?' is the most expensive unanswered question in a migration

Every ECC estate of any age carries a layer of custom code that nobody can fully account for. Reports written for a finance manager who retired, user exits added during a go-live in 2008, Z-tables that a discontinued interface once fed. When a migration team asks the application owners which of it is still needed, the honest answer is 'probably all of it', because the cost of saying 'not needed' and being wrong lands on the person who said it. So the code is carried forward, remediated for S/4HANA syntax and data-model changes, regression tested, and paid for at every future upgrade. Nobody decided to keep it; nobody could prove it was safe to drop.

This is a measurement problem masquerading as a judgement problem. The system already knows what runs. ECC has recorded transaction usage in the workload statistics for decades, and since the ABAP Call Monitor became available the kernel can record every procedure that executes, down to the method and enhancement implementation. The migration's job is to collect that evidence over a long enough window, combine it with static analysis, and then bring the residue, the objects that actually execute, to the business as decisions rather than bringing the whole inventory as a question.

What runtime usage data SAP already gives you

Three SAP-delivered sources answer 'did this execute?' at different granularities, and a serious inventory uses at least two of them.

  • ST03N workload statistics record which transactions and reports were started, by how many users, how often. This is the coarsest view and it is always available, but it misses everything that runs inside a transaction: an exit in MV45AFZZ shows up as VA01 traffic, not as its own line.
  • The ABAP Call Monitor (transaction SCMON) records every executed procedure: programs, function modules, class methods, and enhancement implementations. Its data is aggregated by the SUSG transaction into a compact, long-retention store. SCMON supersedes UPL and is the source the SAP Custom Code Migration app reads when it builds a usage-based worklist. If it is not switched on yet, switching it on is the first action of any pre-migration assessment, because every week of collection makes the evidence stronger.
  • Usage and Procedure Logging (UPL) is the predecessor to SCMON on older kernels and, where it has been running for years, is a valuable historical record even if SCMON is now the live collector.

How long you have to collect, and what a gap in the data means

The single most common mistake is reading a month of SCMON data and declaring everything without a hit unused. Business processes have annual cycles: year-end close programs, quarterly rebate settlements, seasonal pricing, tax reporting that runs once. A credible no-usage claim needs a collection window that covers a full fiscal year, or the object's absence must be explained by something else, such as a static analysis showing it has no active callers and its transaction code was removed from every role. Where a full year is not available, the honest disposition is 'no usage observed in N months' with the residual risk stated, not 'unused'.

Data gaps cut the other way too. SCMON records executions in the system where it runs. A program executed only in a quality system, or triggered by a batch job that was disabled last year, will not appear in production data and might still matter. The evidence has to be read with the landscape in mind, which is why the runtime data is one leg of the analysis and not the whole of it.

Combining usage, where-used, and the business rule into a disposition

Runtime data tells you what ran. Where-used analysis tells you what can run: an include with no SCMON hits but an active caller in a program that does execute is live code on a path that happened not to be exercised. Reading the source tells you what the object is for, which is the only way to decide what to do about the ones that do execute. Put the three together and each object falls into one of a small number of buckets.

Objects with no runtime hits over a full cycle, no active callers, and no role assignment are retirement candidates, and the decision needs no workshop time beyond a sign-off. Objects with hits whose rule exists in S/4HANA as standard configuration or a delivered function, credit checks that FSCM covers, output logic that BRF+ replaces, are retire-and-adopt-standard candidates that go to the fit-to-standard workshop with their execution frequency attached, so the process owner sees 'fires on 3% of orders' rather than a code name. Objects with hits and a rule that standard does not deliver are the genuine extensions, and they are the ones worth remediating to clean-core patterns. On the reference estate, a live ECC system used to validate this approach, the first two buckets together came to roughly 44% of 356 inventoried objects; that is a property of that estate, not a benchmark, and a customer's number comes from their own system.

This is the work an agent can prepare before a consultant is booked. Reading source, running where-used, executing readiness checks, and profiling what each object does across an estate of several hundred objects is weeks of manual effort and hours of governed, read-only tool calls against the live system. Where the customer has SCMON collecting, the usage evidence joins the same inventory. Where a resulting decision is target configuration, the agent drafts a governed customizing transport and the customer's change board decides whether it lands; development systems only, never touching production on its own. Our functional-testing agent, which would prove that the standard step handles the volume the retired exit used to, is in build and design preview, not shipped. SAP's own stated direction, agent-led transformation with a claimed reduction of more than 35% in migration effort (SAP News, Sapphire 2026), rests on exactly this kind of evidence-gathering being automated.

What to do with the answer

The output is a custom-code disposition register with a usage column that has a number in it, and that column changes the conversation with the business. A retirement list with evidence gets signed; a retirement list built on opinion gets debated. It also changes the business case: remediation effort is estimated from the objects that will actually be carried forward, regression scope is drawn from the objects that execute, and the clean-core outcome is a count rather than an aspiration.

The practical sequence is short. Confirm SCMON is on in production and check how far back its data goes. Pull the workload statistics for the same window. Build the static inventory of custom objects and their where-used graph from the live system. Read the rule in each object that executes. Then walk into the fit-to-standard workshop with a register in which most rows already have a defensible disposition and the remaining rows have the evidence a process owner needs to decide in minutes.

Frequently asked

How long should SCMON run before you trust that a custom object is unused?

Long enough to cover every business cycle the object might serve, which for most estates means a full fiscal year including year-end close. If a year is not available, report the finding as 'no executions observed in N months' with the risk stated, and corroborate it with static where-used analysis and role assignments rather than declaring the object unused. Switching SCMON on is the first step of any assessment precisely because the collection window is the constraint.

Is the SAP Custom Code Migration app enough on its own?

It is a strong starting point. It combines SCMON usage data with S/4HANA readiness checks to scope a worklist and it is SAP's supported path. What it does not do is read the business rule inside each object, trace where-used across the process, or connect an object to the standard S/4HANA function that replaces it, which is what turns 'this executes' into 'retire and adopt standard' or 'keep as a clean-core extension'. Use the app for the usage and syntax layer and add the semantic layer on top.

What if a custom object shows usage but the business cannot say why?

That is the case the evidence chain is built for. Read the source to state the rule it enforces, check where-used to find what calls it, and match the rule against standard S/4HANA capability. Most objects in this state turn out to implement a rule the standard now delivers, in which case the disposition is adopt standard and the object retires even though it executes today. The remainder are candidates for a clean-core re-implementation, and the usage frequency tells you how much regression testing that decision carries.

See your own Clean Core Score.

Run the free S/4 readiness scan in under a minute — no system access required.

Keep reading