Skip to main content

Wait For Async Sub-Flows Node

Introduction

The Wait For Async Sub-Flows node (WAIT_FOR_ASYNC_SUB_FLOWS) blocks the parent flow at a join point after it has dispatched one or more async sub-flows (SubFlow nodes with async = true), until those sub-flows satisfy the configured release condition, and only then continues to the following nodes.

Its semantics are similar to Java's Thread.join() or CompletableFuture.allOf().join(): dispatch several async sub-flows in parallel, then wait at one point for them to finish (or reach a threshold) before continuing.

What problem it solves

By default, when a SubFlow node has async = true, the parent flow "returns immediately after dispatch" and keeps going without ever observing the sub-flows' success or failure. When the business needs to "process N sub-flows in parallel first, then wait for them to complete before aggregating/continuing", this node is used at the join point to wait.

Limitations

  • In-memory flows only: this node can only be used in flows whose trigger has "Runs in Memory" enabled. A non-in-memory (persistent) flow containing this node will fail to save/publish with an error, and saving is blocked.
  • Direct sub-flows only: the wait scope is the async sub-flows dispatched directly by the current flow instance (parent_id = current flow instance). It does not recursively wait for grandchild sub-flows. If you need to wait for grandchildren, place another wait node inside the intermediate flow.
  • Timeout does not cancel sub-flows: a timeout only releases the parent flow; already-dispatched sub-flows keep running in the background.

Wait Scope

  • The scope is delimited by flow instance: it waits for all async = true direct sub-flows dispatched "under the current flow instance, before this node".
  • Not divided by thread/iteration: if the async sub-flows were dispatched inside a Repeat (loop) with parallel iterations, sub-flows from all iterations are included in the wait scope.
  • On entry the node scans all async sub-flows under the current instance (whether already finished or still running). "Fast sub-flows" that already completed before the parent reached this node are counted correctly and never dropped.

Completion Modes (completionMode)

The node offers four parallel completion strategies. The node's final status (success / failure) is uniformly determined by onConditionMet (when the condition is satisfied) and onConditionUnmet (when it is not), each with per-mode defaults.

Completion modeWait / release conditiononConditionMet (default)onConditionUnmet (default)
All completed (ALL_COMPLETED, default)Wait for all sub-flows to reach a terminal state; only cares about completion, not success/failureNode is always SUCCESS
All succeeded (ALL_SUCCESS)Wait for all sub-flows to reach a terminal state; requires all to succeedAll succeeded → SUCCESSAny failure → FAILURE
Failure threshold (FAILURE_THRESHOLD)Early-release when failure count ≥ failureThresholdThreshold reached → FAILUREAll done without reaching threshold → SUCCESS
Success threshold (SUCCESS_THRESHOLD)Early-release when success count ≥ successThresholdThreshold reached → SUCCESSAll done without reaching threshold → FAILURE

Notes:

  • Difference between "All completed" and "All succeeded": the former only cares whether sub-flows finished — the node succeeds regardless of outcome; the latter requires all to succeed — a single failure makes the node fail by default.
  • "Early-release" in threshold modes means that once the threshold is met, the parent flow continues immediately, and the remaining running sub-flows are not cancelled — they keep running in the background.
  • The table shows defaults. Both onConditionMet and onConditionUnmet can be manually changed to "success" or "failure" in the config panel to fit your business (for example, letting "All succeeded" mode release as success even when there is a failure).

Configuration

ConfigDescriptionDefault
Completion mode (completionMode)One of the four strategies aboveAll completed (ALL_COMPLETED)
Failure threshold (failureThreshold)Required only for "Failure threshold" mode; must be ≥ 1None (validated at publish time)
Success threshold (successThreshold)Required only for "Success threshold" mode; must be ≥ 1None (validated at publish time)
Node status when condition met (onConditionMet)Success / failurePer-mode default (see table above)
Node status when condition unmet (onConditionUnmet)Success / failurePer-mode default (see table above)
Status when nothing to wait for (notTriggered)If there are no async sub-flows to wait for on entry, the node releases immediately with this status; set it to "failure" to make the flow error out when "there should have been sub-flows but there were none"Success
Wait scope filter (waitForNodeIds)Optional. Restricts waiting to sub-flows dispatched by specific SubFlow nodes. This is a scope filter, not a count contract — it does not mean "must have N". To express "must have N", use a threshold modeEmpty (wait for all async sub-flows)
Timeout (timeout)Optional. Empty means wait foreverEmpty
Timeout unit (timeUnit)days / hours / minutes / secondsseconds
Include sub-flow details (includeSubFlowDetails)Whether the output includes each sub-flow's full outputfalse
Max tracked sub-flows (maxTrackedSubFlows)Cap on the number of detail entries in the output, to avoid output bloat; only truncates the output details and does not affect the correctness of the wait decision500

Timeout

  • After a timeout is configured, if the completion condition is still not met when the timeout fires, the node ends with a success / failure terminal status (via onConditionUnmet, default failure), not a separate "timed out" status. You can branch to an error-handling node based on this.
  • A timeout does not cancel unfinished sub-flows; they keep running in the background.
  • The output marks a timeout release with timeout: true and terminationReason: TIMED_OUT.

Output

After the node reaches its terminal state, the output (referenceable by subsequent nodes) includes:

FieldDescription
nodeResultNode terminal status: SUCCESS / FAILURE
terminationReasonReason code, e.g. ALL_COMPLETED / ALL_SUCCEEDED / SOME_FAILED / FAILURE_THRESHOLD_REACHED / SUCCESS_THRESHOLD_REACHED / TIMED_OUT / NO_ASYNC_SUB_FLOWS
messageA localized one-line description of the result
completionModeThe completion mode that triggered the release
conditionMetWhether the completion condition was met (true → onConditionMet, false → onConditionUnmet; timeout is false)
totalTotal number of sub-flows in the wait scope
success / failure / pendingCounts of succeeded / failed / still-unfinished sub-flows
timeoutWhether the node ended due to a timeout
stillPendingOn early-release or timeout, the list of sub-flow ids still unfinished
subFlowsSummary of each sub-flow (sub-flow unique id, the node that dispatched it, node name, definition id, status; plus output when includeSubFlowDetails = true)
warningsDiagnostics (e.g. the node looks misplaced, details were truncated)

Tip: the sub-flow identifier in subFlows is flowInstanceUniqueId (a UUID), consistent across in-memory and persistent modes.

note

In the flow instance view, this node only shows its output once it reaches the terminal state (DONE); nothing is shown while it is still waiting (IN_PROGRESS).

Typical Usage

  1. Dispatch several async = true sub-flows in parallel using a Repeat loop or multiple SubFlow nodes.
  2. Place a Wait For Async Sub-Flows node after those dispatch nodes.
  3. Choose a completion mode:
    • "Continue once all finish, regardless of outcome" → All completed.
    • "Continue only if all succeed" → All succeeded.
    • "Continue as soon as N succeed" → Success threshold + set the success threshold.
    • "Abort early if too many fail" → Failure threshold + set the failure threshold.
  4. Optionally configure the timeout, the onConditionMet / onConditionUnmet terminal statuses, whether to output sub-flow details, and so on.