Control Flow Nodes
Control flow nodes determine how data moves through your workflow. Use them to branch, loop, run tasks in parallel, pause execution, handle errors, and compose workflows from reusable subflows.
All Control Flow Nodes
Evaluate a condition and route data to the True or False branch. Supports expressions, comparisons, and boolean logic.
Multi-way branching based on a value. Define named cases with match conditions and an optional default fallthrough branch.
Iterate over an array and execute downstream nodes once per item. Access the current item, index, and total count in expressions.
Execute multiple downstream branches concurrently. All branches run simultaneously and results are collected when every branch completes.
Pause workflow execution for a specified duration. Configure delays in seconds, minutes, or hours.
Wrap nodes in error handling. The Try branch executes normally; if any node throws an error, execution jumps to the Catch branch. An optional Finally branch runs regardless of success or failure.
Execute another workflow as a step within the current workflow. Enables modular, reusable workflow design with input/output data mapping.
Run custom JavaScript or Python code in a sandboxed Docker container. Process, transform, or generate data with full programming flexibility.
If/Else Condition
The If/Else node evaluates one or more conditions and directs data down the True or False output. Conditions are defined as a JSON array, and you can combine multiple conditions with AND or OR logic.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| conditions | array | required | Array of condition objects. Each condition has a field, operator, and value. See the operator reference below. |
| combineWith | string | "and" | How to combine multiple conditions: "and" (all must be true) or "or" (any must be true). |
Supported Operators
| Operator | Description |
|---|---|
equals | Exact string or number match |
notEquals | Value is not equal |
greaterThan | Numeric greater than |
greaterThanOrEqual | Numeric greater than or equal |
lessThan | Numeric less than |
lessThanOrEqual | Numeric less than or equal |
contains | String contains substring |
notContains | String does not contain substring |
startsWith | String starts with prefix |
endsWith | String ends with suffix |
isEmpty | Value is null, undefined, or empty string |
isNotEmpty | Value is present and non-empty |
matchesRegex | Value matches a regular expression |
notMatchesRegex | Value does not match regex |
isIn | Value is in a comma-separated list |
isNotIn | Value is not in a comma-separated list |
isTrue | Value is truthy (true, 1, "true") |
isFalse | Value is falsy (false, 0, "false") |
exists | Field exists in the data |
notExists | Field does not exist in the data |
Example
{
"conditions": [
{
"field": "{{ $json.status }}",
"operator": "equals",
"value": "active"
},
{
"field": "{{ $json.score }}",
"operator": "greaterThan",
"value": 80
}
],
"combineWith": "and"
}Switch
The Switch node provides multi-way branching. Define a value expression and one or more cases. Each case creates a separate output port on the node, allowing you to route data to different downstream branches.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| value | string | required | Expression to evaluate (e.g. {{ $json.region }}). The result is matched against each case. |
| cases | array | required | Array of case objects. Each case has a name and a value to match against. Each case creates a dynamic output port. |
| mode | string | "exact" | Match mode: "exact" (strict equality), "contains" (substring match), or "regex" (regular expression match). |
Example
{
"value": "{{ $json.region }}",
"cases": [
{ "name": "US East", "value": "us-east-1" },
{ "name": "US West", "value": "us-west-2" },
{ "name": "EU", "value": "eu-west-1" },
{ "name": "Default", "value": "*" }
],
"mode": "exact"
}Dynamic output ports
Subflow
The Subflow node executes another workflow as a step within the current workflow. This enables modular workflow design. Build reusable logic once and invoke it from multiple parent workflows.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| workflowId | string | required | ID of the workflow to execute as a subflow. Select from the searchable dropdown. |
| inputMapping | object | {} | Map data from the parent workflow into the subflow's trigger input. Keys are subflow input field names, values are expressions. |
| outputMapping | object | {} | Extract fields from the subflow's final output back into the parent workflow's data. |
| timeout | number | 60000 | Maximum time (ms) to wait for the subflow to complete before failing. |
| passCredentials | boolean | false | Whether to pass the parent workflow's credential context to the subflow. |
Example
{
"workflowId": "wf_abc123",
"inputMapping": {
"customerEmail": "{{ $json.email }}",
"orderId": "{{ $json.orderId }}",
"items": "{{ $json.lineItems }}"
},
"outputMapping": {
"confirmationNumber": "{{ $json.confirmation }}",
"estimatedDelivery": "{{ $json.deliveryDate }}"
},
"timeout": 30000,
"passCredentials": true
}Recursion depth
Code
The Code node lets you run custom JavaScript or Python code to process, transform, or generate data. All code executes in a sandboxed Docker container for security. The sandbox is mandatory and cannot be disabled.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| code | string | required | The code to execute. Has access to the items variable containing input data from upstream nodes. |
| mode | string | "javascript" | Programming language: "javascript" or "python". |
The items API
Your code receives an items array containing input data from upstream nodes. Each item is a JSON object. Your code must return an array of items as the output.
// JavaScript example: transform and filter items
const results = [];
for (const item of items) {
// Access input fields
const name = item.json.name;
const score = item.json.score;
// Filter: only keep items with score > 50
if (score > 50) {
results.push({
json: {
name: name.toUpperCase(),
score: score,
grade: score >= 90 ? "A" : score >= 80 ? "B" : "C",
processedAt: new Date().toISOString()
}
});
}
}
return results;Docker sandbox
Loop
The Loop node iterates over an array and executes downstream nodes once for each item. Inside the loop body, you can access:
{{ $json.item }}, the current array element{{ $json.index }}, the zero-based iteration index{{ $json.total }}, the total number of items
Parallel
The Parallel node splits execution into concurrent branches. All branches start simultaneously and the node waits for every branch to complete before merging results and continuing the workflow.
Execution limits
Delay
The Delay node pauses execution for a configurable duration. Use it to add wait times between API calls (rate limiting), schedule follow-up actions, or implement polling patterns.
Try/Catch
The Try/Catch node wraps a group of nodes in error handling. If any node in the Try branch throws an error, execution immediately jumps to the Catch branch. The Catch branch receives the error details. An optional Finally branch always executes, regardless of whether an error occurred.
| Branch | Executes When |
|---|---|
| Try | Always. Contains the primary logic. |
| Catch | Only when an error occurs in the Try branch. |
| Finally | Always. Runs after Try or Catch completes. |