MergeMultiple
Description
Section titled “Description”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.
Configuration
Section titled “Configuration”Parameters
Section titled “Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
| (no user-configurable parameters) | - | - | This module is automatically configured based on the workflow connections. Predecessor modules are detected automatically. |
Output
Section titled “Output”{ "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" }}Usage Example
Section titled “Usage Example”Basic case
Section titled “Basic case”{ "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_statesdatabase 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 markstimedOut: 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_statestable if it does not exist. - If predecessors are missing, it returns a
pendingstatus 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/Mon the canvas where N = groups received and M = total groups expected (e.g.2/2), not the index of the triggering batch item.
Related Nodes
Section titled “Related Nodes”- Decision - splits the flow into two true/false branches
- Switch - splits the flow into multiple routes
- Router - routes by field value
- MergeIterator - merge for iterations
- MergeResults - advanced merge with memory