Skip to content

MergeMultiple

The mergeMultiple module is a convergence node that waits for and combines data from multiple parallel workflow branches. When a flow is split into several branches (for example, via a Decision or Switch), mergeMultiple waits until all predecessor branches have completed their execution before continuing. It uses the database (merge_states table) to store partial data from each branch and verify when all have been received. It supports nested iterations with unique merge keys per level and group. It includes a configurable timeout mechanism (5 minutes by default) to avoid deadlocks if a branch never arrives, and protection against ghost re-executions.

ParameterTypeRequiredDescription
(no user-configurable parameters)--This module is automatically configured based on the workflow connections. Predecessor modules are detected automatically.
{
"nextModule": "siguiente_modulo",
"iterationInfo": { "current": 2, "total": 2 },
"data": {
"merged": {
"rama_A": { "datos": "de rama A" },
"rama_B": { "datos": "de rama B" }
},
"array": [
{ "source": "rama_A", "data": { "datos": "de rama A" } },
{ "source": "rama_B", "data": { "datos": "de rama B" } }
],
"items": [],
"sources": ["rama_A", "rama_B"],
"missingSources": [],
"count": 2,
"totalItems": 0,
"status": "complete",
"timedOut": false
}
}

The iterationInfo field is always included in the response (both when complete and when pending) and reflects the number of merge groups received vs. expected — not the index of the batch item that triggered the call. This is what the canvas progress badge displays.

Pending response (still waiting for branches):

{
"nextModule": null,
"iterationInfo": { "current": 1, "total": 2 },
"data": {
"status": "pending",
"received": ["mergeResults_5"],
"expected": ["mergeResults_5", "mergeResults_10"],
"missing": ["mergeResults_10"],
"progress": "1/2"
}
}
{
"label": "mergeMultiple"
}
  • Predecessor modules are automatically detected from the workflow connections, or can be manually specified via config.predecessors.
  • Data from each branch is stored in the merge_states database table.
  • The unique merge key is constructed as: {workflowId}_{moduleName}_{mergeGroupKey}_{mergeLevel}.
  • Configurable timeout with config.mergeTimeout (in milliseconds). Default: 300000ms (5 minutes). If it expires, it continues with available data and marks timedOut: true.
  • When the Decision node skips a branch, it automatically inserts a “skipped” record to unblock this merge.
  • Protection against ghost re-executions: if the merge has already been completed for the same key, it ignores the duplicate execution.
  • The output includes multiple formats: merged (object by source), array (array of objects), items (unified items from all branches).
  • Automatically creates the merge_states table if it does not exist.
  • If predecessors are missing, it returns a pending status with the list of missing modules and progress.
  • Source tracking in batch execution: when called from inside an Iterator’s batch chain, the engine automatically identifies which predecessor module (mergeResults_5, mergeResults_10, etc.) sent the data. This allows mergeMultiple to correctly track which branches have arrived even when multiple Iterator batches run concurrently.
  • Cross-execution merging (Delay/Wait): because the merge key is based on workflowId (which is reused by delay-resumed executions), a mergeMultiple node can collect inputs from branches that ran in different execution phases — for example, one branch before a Delay and another after the Delay resumes.
  • Canvas progress badge: the node shows N/M on the canvas where N = groups received and M = total groups expected (e.g. 2/2), not the index of the triggering batch item.