Proje vitrini hazırlanıyorPreparing project showcaseПодготавливаем витрину проекта

Automation

Clearing stuck workflow runs: flows that never finished

Half-finished runs pile up quietly and lock contacts out of the flow. Here is how to spot them, when to intervene and how to write a sweep rule that holds.

Rocketly · 2026-09-05

Thursday afternoon, 3:20 pm. An operations lead opens the weekly maintenance list, scans the run history, and something catches her eye: the "Post-quote follow-up" flow shows 63 runs still marked "in progress", and the oldest one started eleven days ago. Eleven days without reaching step two. In this example nobody complained, no customer wrote in to say "you never got back to me" — because nobody notices a message they were not expecting. That is what makes stalled runs dangerous: they make no noise, they accumulate quietly, and they surface later inside your reports.

This piece works through half-finished runs in three stages. First we separate where and why a flow actually stalls. Then we put the "when is a run dead?" question into a table of thresholds and write the sweep rule around it. Finally we turn cleanup from a one-off chore into a weekly habit with numbers attached. In between there is a section on the runs you must never sweep, because some flows are supposed to stay open for months.

What is actually happening when a flow "gets stuck"?

Every automation has two layers: the design and the run. The design is the flow as it sits on the canvas — steps, conditions, waits. A run is one copy of that design started for one person. The run for Sarah moves independently of the run for James, carrying its own step position and its own wait timer. When someone says "the flow is stuck", they almost always mean the individual runs stopped advancing, not that the design broke.

A healthy run has a short life: started, steps processed in order, finished. If there is a wait, the status becomes "waiting" and it resumes when the timer expires. A stall is one of those transitions simply never happening. Three shapes are typical: a wait step whose timer expired but was never woken, a step frozen on an outbound call that never answered, and an approval step nobody touched. What they share is that none of them raises an error. A failed run gets marked failed and shows up in red; a stalled run cheerfully reports "in progress". We covered how conditional rules chain together in our piece on CRM workflow automation — this article is about what happens to that logic once it is running in production.

Making the distinction early matters because the fixes differ. Repairing a design means publishing a new version. Repairing stalled runs means reaching into the past and handling existing records one by one. Fixing the design does not revive the old runs; they need their own pass.

Why an unfinished run is not harmless

"Nothing is being sent anyway, leave it" is a tempting position. But an idle run is not doing nothing. Its most concrete cost is that it locks the person: most automation engines refuse to enrol the same contact in the same flow twice. So when that customer genuinely receives a new quote two weeks later, the engine says "already enrolled" and never starts the run. The customer hears nothing and nobody goes looking for the reason.

The second cost shows up in reporting. A step-by-step funnel tells you exactly where people drop out of a sequence — but stalled runs create a permanent bulge in the middle of it. The "40% drop at step two" you are reading may not be a drop at all; it may be an uncleaned pile. It quietly undermines the numbers you use to make decisions.

The third is timing. Stalled runs sometimes wake up on their own — an infrastructure restart nudges the timer and away it goes. Then an eleven-day-late "Have you had a chance to review the quote?" lands in someone's inbox. That is worse than never sending it. In order status notification flows the sting is sharper still: a "your parcel has shipped" message arriving after the parcel was delivered creates confusion, not confidence.

Where do stalls begin? Six recurring causes

Look at a few hundred half-finished runs and the causes collapse into a surprisingly short list. Knowing them tells you how each case should be handled in the sweep rule.

  • A disconnected channel. The flow has a WhatsApp step but the channel connection dropped or was never made. The step cannot send, often does not error, and waits in line.
  • An open-ended wait condition. "Wait until the customer replies" was written with no ceiling. If the reply never comes, the run waits forever.
  • An unresponsive external system. A webhook fires, the other side is down or very slow. With no timeout defined, the step hangs.
  • An ownerless approval step. The approval exists, but the approver is on leave, has left the team, or never saw the notification.
  • A branch condition that is never met. The if/else has no "otherwise" path, so when the condition fails the run has nowhere to go.
  • Missing data. The step expects a mobile number and the record has none. Some engines treat that as an error, others just hold.

The most common seventh cause is human: the flow is waiting for something to arrive and it never arrives. This is the classic pattern in document collection automation — the ID scan is never uploaded, the run sits in "waiting" for months. The flow is not badly built; the wait simply has no deadline attached.

When do you declare a run dead?

The hard part of cleanup is not deleting, it is deciding. Act too early and you cut off genuinely long-running flows; act too late and cleanup stops meaning anything. That calls for a separate threshold per step type. The table below is a starting template — the numbers are illustrative and should be tuned to the rhythm of your own process.

Run stateNormal durationDead thresholdRecommended action
Scheduled wait stepAs configured in the stepConfigured time + 24 hoursWake it, then flag it
Pending approval1-2 business days3 business daysEscalate, then close
Outbound call responseSeconds15 minutesRetry, then mark failed
Step with channel errors-3 failed attemptsReport the channel, close the run
Total run lifetimeDepends on the design2x expected lifetimeReview and archive

The logic of each row is the same: define "normal" first, then set the threshold as normal plus headroom. Writing the threshold as a multiple of the expected duration rather than an absolute number means the rule moves with the flow when the design changes. The overrun mechanic will feel familiar if you have built escalation automation against an SLA — there too, crossing a threshold pushes work up a level. The only difference is that here the thing crossing the line is a run record, not a ticket.

How do you write the sweep rule?

A cleanup rule has four parts. Scope: which flows' runs does this rule govern? Starting with a single flow is by far the healthiest approach. Threshold: the duration from the table above. Action: flag, retry, close or archive. And record: whatever you did to a run should be written down somewhere.

Those four map onto two concrete Rocketly features. Stuck flow cleanup detects and sweeps half-finished runs, so records past the threshold stop piling up in the list looking active. Run history and retry carries the history of the decision: every run keeps its record, and failed flows can be retried in bulk rather than one at a time. In other words, the answer to "what happened here?" is not erased — only the run's open state is closed.

The most common mistake is jumping straight to deletion on day one. Start with a report-only pass instead: list the runs past the threshold and just look at them for a week. That week teaches you two things — whether the threshold is too tight or too loose, and whether one flow name keeps repeating in the list. Teams used to managing service thresholds will recognise the reflex; measuring before enforcing is exactly how call centre KPIs like AHT and service level are introduced without wrecking morale.

Once a day is a sensible sweep frequency. Hourly adds needless risk to flows with long waits. Weekly is too sparse: it extends the window in which a stalled run keeps a contact locked out.

Which runs should never be swept?

Not every long-running run is a stalled one. Some flows are designed to stay open for weeks or months, and sweeping them causes real damage. That is why the first line of any sweep rule should be an exception list.

The first exception is time-spread sequences. A drip sequence is different from a trigger-based flow: its steps advance over days and weeks, and the gaps between them are the design. A run waiting on day twelve of an onboarding sequence is a healthy run. The second exception is calendar-anchored flows. Birthday and anniversary automations wait a full year by definition; closing those records because they "haven't moved in twelve months" breaks the flow at its root.

The third exception is contract and interval tracking. In maintenance contract management the next service date may be six months out, and the run waiting in between is doing precisely its job. The practical way to separate these three groups is to tag each flow design with an "expected maximum lifetime". The sweep rule reads that tag first and falls back to the default threshold when there is none — so protecting long flows never requires typing an exception by hand.

Delete, retry or close?

When you find a stalled run you have three options, and which one is right depends on what the step does. If the step has not sent anything outward yet, retry is best: it picks up where it left off. If the step already sent a message and the stall came afterwards, a retry can put the same message out a second time. That is why repeat safety matters: in Rocketly's sequence step editor, steps carrying text can define A/B variants, and the variant choice is locked at run time so that a retry does not fire a second message. It is a concrete example of designing steps to be safely repeatable.

The third option is to close the run without doing anything at all. That is the right call for work that has simply aged out: waking a four-month-old quote follow-up today serves nobody. Writing a closing reason onto the run makes the later analysis much easier.

The most common side effect of retrying is producing duplicate records, especially when the flow creates something. Opening a second record for the same person inflates the work of deduplicating leads in the CRM. So a retry rule should almost always include an "if this step already succeeded, skip it" guard.

Design habits that prevent stalls in the first place

Cleanup treats the symptom. The real gain is building flows that do not stall. Five habits cover most of it.

First, cap every wait. Instead of "wait until they reply", write "wait until they reply, up to three days"; at the end of day three the run has somewhere to go. Second, give every branch an "otherwise" path. Third, attach approvals to a role rather than a named person, so one person's holiday does not freeze the queue. With a wait-for-approval step the flow will not advance unapproved when the timer expires — but the pending record at least becomes visible and can be escalated.

Fourth, test before publishing. A dry run walks the flow end to end on sample data and shows step by step what would execute, without sending real messages. Most stalls surface on the first real execution, so not having your first real execution happen in production is a direct win. Fifth, keep changes reversible: every save is stored as a version, so rolling a broken flow back is one click. That matters most in form abandonment recovery flows, where the window is narrow and even a single broken day produces losses you cannot recover.

How do you know the cleanup is working?

Turning maintenance into a routine requires seeing the result. Four numbers are enough. First, the count of open runs at end of day. That line should be flat over the weeks; if it climbs steadily, the threshold is too loose. Second, the median age of open runs — median rather than mean, because a handful of very old records skews the average. Third, the share of runs being swept out of the total; if that share falls, the design habits are landing. Fourth, the re-stall rate: of the runs you swept and restarted, how many stall again at the same step?

None of this has to be tallied by hand. Analytics and logs show how long each step took and where it stalled; automatic diagnostics finds broken steps, flows that never triggered and unconnected channels and reports them without you going looking. The funnel analysis and diagnostics screen asks the same question from the contact's side: at which step does the drop-off begin? Together they show whether the picture actually improved after a sweep.

The last link in the chain is ownership. Half an hour of checking a week prevents a three-month backlog. Tie that check to a role rather than a person so it survives holidays and handovers. Over time part of it automates too — scanning pending records and summarising them is well within the range of tasks autonomous AI sales agents can take on for a team.

If you want to try this on your own flows, start a free Rocketly account and set up a sweep rule on one flow before rolling it wider.

FAQ

Does deleting a stalled run delete the data too?

No. A run record tracks a flow's progress for one person; it does not contain the contact, lead or task records themselves. Closing a run only ends that progress. And because run history is retained, the "what happened here?" question can still be answered afterwards.

How many days should pass before I call a run dead?

There is no single correct number; it depends on the step type. The practical approach is to write down the flow's expected lifetime and set the threshold at twice that. Two days for a one-day follow-up flow, a year for a six-month service cycle. What matters is that the threshold is defined alongside the flow.

What if I accidentally cut off a flow that was genuinely running?

That is exactly why the first week should be a report-only pass. If a run is closed by mistake you can enrol the person into the sequence manually, without waiting for a trigger to fire. Even so, prefer closing over deleting in the early days.

If I could change one thing to prevent stalls, what should it be?

Put a ceiling on every wait step. Unbounded waits are the single largest source of long-term accumulation. The moment a ceiling exists, the worst case is that the run takes the "timed out" branch and becomes visible there — and a visible problem is a solvable one.