Development Choices

Recovering No-Code Workflows from Partial Failure

Author
Joseph TrasattiMember of technical staff
Published
Section
No-Code
Length
12 min read3 sources cited
A modular workflow conveyor reversing selected completed stages while preserving unaffected work

Recover a partially failed no-code workflow by classifying each completed step as retryable, compensable, or irreversible; recording durable outcomes and compensation state; and routing each failure class to a bounded retry, compensation path, or manual review. Never replay an uncertain side effect unless duplicate execution is known to be safe.

Recovery depends on what already happened

A no-code flow classifies a partial failure, retries or compensates, reconciles state, and may enter a human queue
Partial failure is a state to resolve, not merely a red run.

Recovery from partial failure means returning a workflow and every system it changed to a known, valid state after only part of the run completed. The correct response depends on the effects already committed, not merely which block is marked failed in the editor.

A workflow that fails halfway is not necessarily rolled back. Earlier blocks may have created records, changed metadata, sent requests, or triggered work that continues outside the no-code platform. The failed block may also have completed remotely even though the workflow never received its response. Recovery therefore starts with an effect inventory: what definitely happened, what definitely did not happen, and what remains uncertain.

Classify completed steps as compensable, retryable, or irreversible before choosing whether a failed run should resume, compensate, or enter manual review. Record the classification in the workflow design rather than deciding it during an incident.

Compensable steps

A compensable step has a separate action that can bring the affected system to an acceptable business state. That action is not necessarily a technical rollback. Canceling a reservation, withdrawing a publication, or issuing an adjusted refund may compensate for an earlier action without restoring every field to its previous value.

The Microsoft Compensating Transaction pattern, updated 2026-04-20, explains why this distinction matters: restoring an old snapshot can overwrite concurrent work, while compensation must account for changes made after the original step. It also notes that compensation order can differ from forward-execution order and that some compensations can run in parallel.

For every compensable block, define the compensating operation, the identifiers it needs, its success condition, and the point after which it is no longer valid. Preserve the original operation identifier or returned resource identifier; a label such as asset name or customer name may not identify the exact effect to undo.

Compensation costs another operation against the affected service, additional workflow actions, and engineering time for business-specific reversal logic. It is the wrong answer when the system cannot reliably reach a valid state through reversal, when temporary inconsistency is unacceptable, or when the supposed reversal would erase legitimate concurrent work.

Retryable steps

A retryable step can be repeated without producing more than the intended effect. That normally requires an idempotent operation, a stable idempotency key understood by the receiving service, or a lookup that proves the effect has not already happened.

Retryability is a property of the complete interaction, not of the connector block. A platform may let an operator press retry while the downstream endpoint treats every request as a new instruction. Likewise, a read can usually be repeated without duplicating an effect, but a create, publish, charge, delete, or notification action needs an explicit guarantee from the receiving system before it should be classified as retryable.

A retry adds latency and consumes another action or state transition. Repeated retries can also extend a run beyond its useful deadline. Retrying is the wrong answer when the first request may already have committed, when the input is invalid, when a business rule rejected the request, or when the downstream operation has no duplicate protection.

Irreversible steps

An irreversible step has an effect that cannot be safely undone or repeated. The technical system may offer a second action, but that does not make the original effect reversible if a person or another system has already acted on it.

Place irreversible work after critical validation and after compensable prerequisites have succeeded. If a later step can still fail, define whether the workflow may keep the irreversible effect and resume forward, or whether the run must wait for a person to choose a valid outcome. A generic rollback branch is not enough.

The cost is reduced automation: some failed runs require an operator, a documented decision, and possibly coordination with the system owner. Treat that as a designed recovery path. Automation is the wrong answer when the decision is high-impact, ambiguous, or governed by business rules the workflow cannot evaluate reliably.

Choose the recovery route from the classifications

Resume when the completed prefix can remain in place and the failed or uncertain step can be retried safely. Resume from the first unconfirmed step, not automatically from the beginning of the flow.

Compensate when forward completion is no longer valid and every completed effect that must be reversed has a defined compensating action. Compensation should produce an acceptable current state; it does not promise to recreate the state that existed before the run.

Enter manual review when any completed effect is irreversible, a remote outcome is unknown and cannot be reconciled, compensation has exhausted its own safe retries, or business policy must decide between continuing and reversing. The review record must show the evidence behind the decision.

Persist outcomes outside the editor run

The editor’s run history is useful evidence, but it must not be the only recovery state. Persist step outcomes and compensation progress outside the transient editor run so recovery can continue after another timeout or platform restart.

Use a durable recovery record keyed by a stable workflow-instance or business-operation identifier. At minimum, it should preserve:

Persist the intent to call an effect-producing service before making the call, then persist the observed result after the response arrives. A crash between those writes leaves the step uncertain rather than incorrectly marking it failed. Recovery can then query the receiving system, use a stable operation key, or route the run to review instead of blindly issuing the request again.

Do the same for compensation. A compensating transaction can itself fail, so each completed compensating action needs a durable checkpoint. On restart, the recovery flow reads those checkpoints and continues from the unresolved compensation rather than replaying every reversal. Microsoft’s pattern specifically requires recording compensation progress and making compensating commands idempotent because they may run more than once.

External persistence costs storage operations, connector actions, a small state model, retention work, and an operator view. Excessive custom logging can also add actions and reduce workflow performance. Keep diagnostic events in the operational observability record, while the recovery store holds only the state required to decide and continue recovery.

A separate recovery store is unnecessary for a single read-only action whose repetition has no side effect. It becomes necessary once a run can commit more than one independent effect, outlive the editor’s execution window, or require compensation after the original run has ended.

Configure run-after and retry by failure class

A failed status is too broad to determine recovery. Configure run-after and retry behavior by failure class; applying the same automatic retry to business rejection, throttling, and unknown network outcomes creates duplicate effects.

The Power Automate error-handling guidance, updated 2025-07-11, documents run-after branches for success, failure, timeout, and skipped outcomes, along with fixed or exponential retry policies for transient failures. Those platform statuses are useful routing inputs, but they do not replace domain classification. A timeout says the caller stopped waiting; it does not prove whether the downstream effect committed.

Group related blocks into a scope when they share one recovery boundary. A catch branch should record the failing action, classify the failure, and terminate or route the run deliberately. Allowing later success-path blocks to execute after an unclassified failure can create another partial state that the original recovery design did not cover.

Business rejection

A business rejection is a definite response that the requested operation is not acceptable under current rules. Retrying the same input without changing the condition does not address the rejection. Route it to a terminal business outcome, compensate earlier effects if the operation must be abandoned, or request a human decision when policy allows the input to be corrected.

Do not hide business rejections inside a generic technical-failure counter. Operators need to distinguish an invalid request from an unavailable service, and the recovery record must retain the rejecting response needed to decide what happens to earlier effects.

Throttling and other identified transient failures

Throttling can be retried only when the operation itself is safe to repeat. Use a bounded retry policy with increasing delays; add jitter when the platform supports it so many failed runs do not retry together. Exhaustion must transition to a catch or recovery state rather than leaving the run indefinitely active.

The AWS Step Functions error-handling documentation, accessed 2026-08-26, shows the required separation explicitly: retriers match named error classes, while catchers route execution after no retry matches or retries are exhausted. Its documented defaults are a one-second initial interval, three maximum attempts, and a backoff multiplier of 2.0; it also supports maximum delay and full jitter. These are AWS defaults, not universal recommendations. Set limits from the downstream contract and the workflow’s deadline, and account for retries as additional state transitions.

Check the receiving service’s current limits before choosing an interval or attempt count. The practical controls belong with the downstream rate-limit handling, not in one global retry setting applied to every connector.

Unknown network outcomes

An unknown network outcome occurs when the workflow cannot tell whether the receiving service committed the operation. A lost response, connection interruption, or caller timeout can leave the local run failed while the remote effect succeeded.

Do not treat this as an ordinary transient failure. First reconcile by a stable operation identifier or query the remote state. If the endpoint supports a documented idempotency mechanism, retry with the same key rather than generating a new request. If neither reconciliation nor duplicate protection is available, enter manual review.

This is especially important for external API calls made through no-code HTTP request blocks. The block’s retry switch cannot make a non-idempotent endpoint safe. The receiving API’s semantics determine whether a repeated request resumes the intent or creates a second effect.

Configuration, permission, and runtime failures

Malformed inputs, missing permissions, and deterministic runtime errors should bypass automatic retries unless the platform documents a transient subtype. Repeating the same request consumes actions without changing the condition. Route the run to a failure record containing the relevant configuration or input reference, then resume only after the condition is corrected and the earlier effects have been reassessed.

Keep the catch-all branch last. A wildcard handler is useful for preserving an unrecognized failure, but it should default to an uncertain state or manual review rather than assuming every unknown error is retryable.

Compensation is another failure-prone workflow

A compensation path needs the same controls as the forward path: durable progress, bounded retries for identified transient failures, catch handling, correlation, and a terminal manual-review state. Calling it rollback can obscure this. It is a new sequence of business operations running against systems that may have changed since the original actions.

Do not assume compensations must run in exact reverse order. Define dependencies and prioritize the effects that create the greatest inconsistency if left active. Parallel compensation is appropriate only when the actions do not depend on one another and their combined execution is safe.

Each compensating action must recognize an already-compensated result. If a timeout occurs after the reversal committed but before its success was recorded, the next recovery attempt must reconcile or safely repeat it. Otherwise the compensation path can create the same duplicate-effect problem it was meant to solve.

Compensation adds implementation work for every effect-producing block and must be revised when downstream contracts change. It is the wrong mechanism when the original operation is safely retryable, when strong atomic consistency is required, or when no business-valid reversal exists.

Manual review needs a durable contract

Manual review is a workflow state, not an alert sent after the automation gives up. The review item should identify the run, show confirmed and uncertain effects, include the last response or error, list completed compensation, and state the permitted decisions. An operator should not have to reconstruct the run from screenshots or an expired editor session.

Record the review decision before resuming or compensating. If the operator starts an external corrective action, record its identifier and outcome in the same recovery history. That lets another operator continue after a shift change or platform restart without repeating the correction.

Manual review costs response time and staff attention, so reserve it for ambiguous, irreversible, or high-impact cases. It is still cheaper than automating a guess that can duplicate an external effect or reverse the wrong operation.

Check recovery before publishing the flow

Exercise the failure boundaries that matter: before an external call, after the receiving service accepts it but before the result is stored, during a later step, and during compensation. Confirm that another run can read the durable record and continue without relying on the original editor execution.

Verify that retry exhaustion reaches a defined recovery state, an uncertain remote result cannot be replayed automatically, and compensation resumes from its last confirmed checkpoint. Confirm that every irreversible step either follows all critical validation or has an explicit manual-review route.

Finally, check the downstream documentation for idempotency, status lookup, rejection codes, throttling signals, and reversal operations. For outbound event effects, pair recovery state with webhook-delivery monitoring so a completed workflow is not mistaken for confirmed downstream processing. A flow is ready when every effect-producing block has a documented recovery disposition and every recovery path can survive the loss of the run that started it.

Sources

  1. Microsoft Compensating Transaction patternlearn.microsoft.com
  2. Power Automate error-handling guidancelearn.microsoft.com
  3. AWS Step Functions error-handling documentationdocs.aws.amazon.com

See also