SAP long-running job monitoring fails when it treats every long job as the same event. A failed job produces a cancelled status, a log entry, an alert and an owner. A hung job produces none of those: it sits in SM37 as Active while its duration counter climbs, and nothing in the standard toolset decides that it has stopped doing useful work. The diagnosis has to separate 3 states that a runtime alert collapses into one, namely a job that is genuinely slow, a job that is blocked on a resource, and a job that has been abandoned by its work process, because the correct recovery action differs in each.
Together they give SAP Basis and operations teams a repeatable sequence, from SM37 through SM50, SM66, SM12, SM13 and ST22, for reaching the right decision before the backlog does the deciding for them.
Why a Hung SAP Job Is Harder to Catch Than a Failed One
A hung background job survives because nothing in the ABAP stack is designed to terminate it. Dialog work processes have a runtime ceiling: historically rdisp/max_wprun_time applied only to dialog processes, and background work processes were exempt. In SAP S/4HANA 2020 and later, that parameter has been removed from the kernel in favour of priority-based dialog time-outs, and the exemption for background work remains. A batch step can wait on a lock, a remote partner or an update record for days without tripping a single system-side guard.
The second reason is that SM37 displays the job status exactly as it is stored in the database. If the work process that owned the job terminated without a controlled clean-up, the status row is never rewritten. The job is Active in table TBTCO and absent from every process overview at the same time. Any long-running job monitoring that reads SM37 or TBTCO sees a running job. There is no running job.
The third reason is organisational rather than technical. A cancelled job has a log line that names a cause, so the ticket routes itself. A hung job has a log that ends mid-step, so the ticket routes to whoever is awake. Most of the time lost on hung SAP jobs is spent deciding who should look and what they should look at first.
The 3 States Monitoring Collapses Into One
A runtime threshold treats slow, blocked and abandoned jobs as the same event, and that is the root of most wrong recovery decisions. The 3 states look identical in SM37. They separate cleanly in SM50 and SM66.
Figure 1. One SM37 row, 3 different states, 3 different recovery actions.
| State | What SM37 shows | What SM50 or SM66 shows | Correct action |
|---|---|---|---|
| Genuinely slow | Active, duration rising, job log updating between steps | Work process in Running status, CPU time increasing, Table or Action column changing on refresh | Leave it running. Investigate volume and SQL with STAD and ST05 after completion. |
| Blocked | Active, duration rising, job log static | Work process in Hold or Stopped status with a Reason value (ENQ, RFC, CPIC, UPD, PRIV) | Identify and release the blocker. Cancel only if the blocker cannot be released. |
| Abandoned | Active, duration rising, no log update for the full period | No work process on the instance named in the job details, or a work process in Ended status | Run SM37 Job → Check Status, then restart from the failed step. |
The blocked state is the one that costs the most, because it is the one most often misdiagnosed as slow. A blocked job consumes no CPU and touches no table. Its duration counter is the only thing moving.
The First 5 Minutes: Confirming the Job Is Still Attached to a Work Process
The first diagnostic question is not why the job is slow but whether the job still exists as a process. Everything downstream depends on that answer, and it takes 4 steps to get it.
Figure 2. The first 5 minutes: SM37 to SM50 to SM66, and what each result decides.
| Step | Transaction | What to read | What it tells you |
|---|---|---|---|
| 1 | SM37 | Job details: target server, work process number, PID, and the timestamp of the last job log line | Which instance to open and how long the log has been silent |
| 2 | SM37, Job → Check Status | Status after the check runs | If the status flips to Cancelled, the job was abandoned. The check corrects a stale Active or Ready status against the real process state (SAP Learning). |
| 3 | SM50 on the named instance | The BTC work process matching the PID: Status, Reason, CPU, Time, Report, Table columns | Whether the process is Running, on Hold, Stopped or Ended, and what it is waiting on |
| 4 | SM66 | Global process overview filtered to BTC type | Whether the wait is isolated to this job or shared across instances, which points to a system-wide blocker |
If Step 2 changes the status, stop diagnosing and move to recovery. If Step 3 shows a Running process with CPU time advancing, the job is slow, not hung, and the investigation becomes a performance question. If Step 3 shows Hold or Stopped with a populated Reason column, the job is blocked, and the Reason value chooses the next transaction. The Check Status function is documented in SAP Learning’s background processing lesson.
Reading the Reason Column: What the Job Is Waiting On
The Reason column in SM50 is the single most useful field in the diagnosis of a hung SAP job, because it names the resource the job is waiting for. SAP documents the typical hold reasons as debugging, CPIC activity, locks, updates, GUI response and PRIV memory mode. Each maps to a different diagnostic branch.
Figure 3. The SM50 Reason column mapped to the next transaction and the recovery decision.
| Reason in SM50 | What the job is waiting on | Where to look next | Recovery decision |
|---|---|---|---|
| ENQ | An SAP lock held by another process or session | SM12: find the lock owner, user, and lock age. SM04 or AL08 to confirm whether the owning session is still alive. | Release the lock only if the owner is a dead session. Never delete a lock held by a running process. |
| RFC (SM50) or CPIC (SM66) | A synchronous call to a partner system that has not replied | SM59 connection test to the destination. SMGW for the gateway connection. SM58 for tRFC errors, SMQ1 and SMQ2 for qRFC queues. | Restore the partner or the gateway. If the partner is permanently down, cancel and restart after connectivity returns. |
| UPD | Update task completion after COMMIT WORK AND WAIT | SM13 for update records in Init or Error status. SM14 to confirm the update server is active. | Reactivate updates or clear the erroring record. The job resumes on its own once V1 completes. |
| PRIV | Private memory mode after exhausting extended memory | ST02 for extended memory usage and the heap limit. The job is holding the process exclusively. | Let it finish if progress is visible. Otherwise cancel and reduce the data volume per step before restart. |
| Blank, status Running | Nothing external. The job is executing. | Watch the Table and Action columns across 3 or 4 refreshes. STAD after completion, ST05 during. | No recovery. Performance analysis. |
Work process exhaustion
Work process exhaustion presents in 2 different places depending on which pool ran out. If every BTC work process on the instance is occupied, a released job never becomes Active at all. It sits in Ready, and the job scheduler has nowhere to place it. The tell is RZ04 or SM50 showing all BTC processes busy while SM37 shows a queue of Ready jobs whose start time has long passed.
The subtler case is a job that is Active but whose parallel child tasks have nowhere to run. A step that fans out work through asynchronous RFC calls needs free dialog work processes in the target RFC server group, and if that group is saturated the parent step waits on children that never start. SM50 shows the parent on Hold with reason RFC even though the partner is the same system. RZ12 shows the server group resource limits that are starving it.
Table locks and enqueue waits
Two different lock layers produce an identical symptom from the job’s point of view, and confusing them wastes the first hour. An SAP enqueue lock lives in the enqueue server and appears in SM12 with an owner and a timestamp. A database lock lives in the database and appears in DBACOCKPIT or the database’s own monitoring, with no entry in SM12 at all. A job on Hold with reason ENQ is waiting on the first kind. A job in Running status that makes no progress and shows the same table name across every refresh is usually waiting on the second.
The recovery rule is the same for both: identify the holder before touching the lock. A lock whose owner is a dead GUI session or a cancelled job can be released. A lock whose owner is another active batch step must be left alone, and the recovery decision becomes a sequencing question about which job should have run first.
RFC connections waiting on a partner that will never answer
A synchronous RFC has no notion of a dead partner until the underlying CPIC layer gives up. SAP’s own guidance on work processes stuck in On Hold with reason RFC, or Stopped with reason CPIC, treats the condition as a hang requiring gateway and destination analysis rather than a normal wait. The diagnostic sequence is SM59 to test the destination, SMGW to confirm the gateway still holds the connection, and SM21 on both systems for the timestamp at which the partner went quiet.
The delta here is not only the job’s own lost time. Any tRFC or qRFC traffic behind the same destination is queuing in SM58, SMQ1 and SMQ2 while the partner is unreachable, and it will all release at once when connectivity returns.
Update task backlogs
An update backlog freezes every job that waits on its own updates, not only the one under investigation. When the update server is deactivated, whether by an administrator after a database fill-up or by a V1 error that triggered automatic deactivation, records accumulate in SM13 in Init status. Any batch step that issued COMMIT WORK AND WAIT holds until its record is processed. SM14 shows whether updates are active, and SM13 shows how deep the queue has grown and which records are in Error. Reactivating the update server, or repairing the erroring record, releases the whole set without any job-level intervention.
The Cost of Every Hour: The Delta That Grows While the Job Does Not Finish
A hung job is not a static problem, because the environment around it keeps moving while it does not. Each hour of hang adds to a delta that the recovery has to absorb, and the size of that delta often matters more to the recovery decision than the cause of the hang.
Figure 4. What accumulates behind a hung job, hour by hour (illustrative).
| What accumulates | Where it shows | Recovery consequence |
|---|---|---|
| Downstream jobs in the chain waiting on this job’s event or completion | SM37 Released or Ready jobs with start conditions after job or after event | Every dependent job runs late and compressed into the same window once released, competing for the same work processes. |
| Delta records the job was meant to consume | Change pointers, delta queues, IDoc status 64 in WE02, extraction queues | The restart processes hours or days of volume in a single run, which is itself a performance risk. |
| Locks the hung job is holding | SM12 entries owned by the job’s user and PID | Other jobs and dialog users block behind the hung job, producing a second wave of hangs with a different visible cause. |
| Dumps in child tasks or partner systems | ST22 for the same user and time window, on both systems | A child aRFC that dumped with a memory error does not cancel its parent. The parent waits for a reply that will never come, and ST22 is the only place the real cause is written down. |
ST22 deserves a specific check in every hung-job diagnosis even when the job itself has no dump. The runtime error that explains the hang is frequently in a different process, on a different instance, or in the partner system.
Choosing the Recovery Action: Wait, Release the Blocker, or Cancel and Restart
The recovery decision follows from the state, not from the duration, and there are only 3 decisions available. A slow job is left alone. A blocked job is unblocked at the resource, not at the job. An abandoned job is status-corrected and restarted from the step that did not complete.
Figure 5. The 3 recovery decisions and the checks before and after each.
| Diagnosed state | Action | Before acting, confirm | After acting, verify |
|---|---|---|---|
| Genuinely slow | Wait. Extend the downstream window if the chain allows it. | CPU time and table access are still advancing across successive SM50 refreshes. | Job log reaches the next step within the projected interval. |
| Blocked on ENQ or database lock | Release the lock if the owner is dead, or wait for the owning step to finish. | Lock owner identity and liveness in SM12 and SM04. | SM50 reason clears and the job log resumes. |
| Blocked on RFC or CPIC | Restore the partner or gateway. Cancel the job only if the partner outage will outlast the window. | SM59 test result and SM21 on the partner system. | SM58, SMQ1 and SMQ2 drain, then the job log resumes. |
| Blocked on UPD | Reactivate updates in SM14 or repair the erroring record in SM13. | The Error record’s cause, so the same failure does not recur immediately. | SM13 queue drains and the job completes without restart. |
| Abandoned | SM37 Check Status, then restart from the failed step. | Whether the failed step is restartable without duplicating what it already posted. Check what was committed before the process died. | The restarted step completes and downstream events fire. |
Cancelling a blocked job is the most common wrong action, because it removes the symptom and preserves the cause. The lock holder, the dead partner or the deactivated update server is still there, and the restarted job blocks again on the same resource within minutes.
Why Runtime Thresholds Fail at SAP Long-Running Job Monitoring
A runtime threshold detects duration and nothing else, which is why it generates the alert and then leaves the recovery decision exactly as hard as it was. The alert tells the operator that the job has exceeded a limit. It does not say whether the work process is running, on hold or gone, what the Reason column reads, who holds the lock, or how much delta has accumulated behind the job. The operator still has to run the sequence above from the start, and the threshold is usually tuned so loosely to avoid month-end false positives that the hang has been under way for hours before it fires.
Figure 6. A duration alert versus the context the recovery step needs (illustrative).
The abandoned state defeats threshold alerting entirely. The duration counter in SM37 keeps advancing on a job that has no process, so the alert reports a long-running job when the truth is a dead one. Recovery for that state is a status correction and a restart, and a duration alert points in the wrong direction.
What the recovery step needs is the context the diagnosis produces: the state, the wait reason, the blocking resource and the downstream dependencies, carried into the decision rather than reconstructed by hand after the alert. Automating SM37 job monitoring only helps if that context travels with the alert. Symphony is one example of a layer built to carry it into the recovery step, so that the choice to wait, release or restart is taken with the job’s wait state and its downstream chain in view rather than its clock alone. Its SAP job orchestration capabilities and failed job recovery approach describe how that context reaches the operator, or the automated recovery path, before the delta grows.
From Silent Job to Decided Action
A hung SAP job never announces itself, so the diagnosis has to be a habit rather than a reaction. Confirm the process exists. Read the Reason column. Follow it to SM12, SM59, SM13 or ST22. Size the delta. Then choose between waiting, releasing the blocker, and restarting from the failed step, with the state deciding the action rather than the duration. Teams that run this sequence consistently recover hung jobs before the downstream chain notices, and teams that rely on runtime thresholds recover them after it does.
If you want to see how that context-carrying recovery step behaves against your own job chains, see how it works in your environment.
Frequently Asked Questions
What is SAP long-running job monitoring?
SAP long-running job monitoring is the practice of detecting background jobs that exceed their expected runtime and determining whether each one is slow, blocked or abandoned before acting. It combines SM37 job status with SM50 and SM66 work process state, because runtime alone cannot distinguish a job that is working from one that has stopped.
How do you diagnose a hung SAP background job?
Start in SM37 with the job details and Job → Check Status to confirm the job still has a process. Then open SM50 on the named instance and read the Reason column. ENQ points to SM12, RFC or CPIC to SM59 and SMGW, UPD to SM13 and SM14, and a Running status with advancing CPU means the job is slow rather than hung.
Why does a job show Active in SM37 but does not appear in SM50?
SM37 displays the status stored in the database, not the live process state. If the work process terminated without a controlled clean-up, the status row is never corrected. Running Job → Check Status in SM37 compares the stored status with the real process and sets it to Cancelled if the job was abandoned.
Does rdisp/max_wprun_time stop long-running SAP background jobs?
No. The parameter applied only to dialog work processes, and background work processes have never had a system-side runtime limit. In SAP S/4HANA 2020 and later the parameter has been removed in favour of priority-based dialog time-outs, and background jobs remain exempt. A hung batch job will run until something releases it or an operator cancels it.
Should I cancel a hung SAP job or wait for it?
The answer depends on the diagnosed state, not the duration. A slow job with advancing CPU should be left to finish. A blocked job should be unblocked at the resource, because cancelling it leaves the lock, the dead partner or the deactivated update server in place and the restart blocks again. An abandoned job should be status-corrected in SM37 and restarted from the failed step.