Loop
Iterate over arrays, objects, or execute a specified number of times with full context access.
The Loop node provides powerful iteration capabilities for workflows, allowing you to process arrays, objects, or execute a block of nodes a specific number of times. Each iteration has access to the current item and index through the workflow context.
┌───────────────────────────────────────────────────────────┐
│ LOOP ITERATION │
├───────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌───────────────────────────┐ │
│ │ START │────▶│ Loop Node │ │
│ └─────────┘ │ • Array: [1,2,3] │ │
│ │ • Index: 0,1,2... │ │
│ └─────┬────────────────┬────┘ │
│ │ │ │
│ (LOOP) (DEFAULT) │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Process │ │ AFTER │ │
│ │ Current │ │ LOOP │ │
│ │ Item │ │ COMPLETE│ │
│ └─────────┘ └─────────┘ │
│ │ │ │
│ │ │ │
│ └────────────────┘ │
│ (back to loop) │
│ │
└───────────────────────────────────────────────────────────┘Configuration
| Property | Value |
|---|---|
| Workflow Types | Workflow |
Output Configuration
Loop Type
Configure how the loop operates:
| Field | Type | Options | Default | Description |
|---|---|---|---|---|
| Type | Select | FOR | FOR | Iteration method (WHILE support coming soon) |
Value Input
Define what to iterate over or how many times to iterate:
| Field | Type | Default | Description |
|---|---|---|---|
| Value | Any | - | Array/object to iterate or number for count-based loops |
Index Management
| Field | Type | Default | Description |
|---|---|---|---|
| Index | Integer | 0 | Current iteration index (automatically managed) |
Loop Outputs
Loop nodes provide context data that can be accessed in connected nodes:
| Output | Type | Description |
|---|---|---|
| item | Any | Current iteration item (for arrays/objects) |
| index | Integer | Current iteration index (0-based) |
Accessing Loop Outputs:
// Access current item
{{ctx.nodes.loopNode.outputs.item}}
// Access current index
{{ctx.nodes.loopNode.outputs.index}}
// Use in conditions
{{ctx.nodes.loopNode.outputs.index < 5}}FOR Loop Implementation
Array Iteration
Process each element in an array:
Configuration:
- Type:
FOR - Value:
["apple", "banana", "cherry"]or{{ctx.nodes.dataSource.outputs.fruits}}
Iteration Behavior:
// Iteration 0: item = "apple", index = 0
// Iteration 1: item = "banana", index = 1
// Iteration 2: item = "cherry", index = 2Example Use Case:
// Process each user in a list
Value: {{ctx.nodes.userApi.outputs.users}}
// In loop body, access current user:
{{ctx.nodes.loopNode.outputs.item.name}}
{{ctx.nodes.loopNode.outputs.item.email}}Object Iteration
Process key-value pairs in an object:
Configuration:
- Type:
FOR - Value:
{"name": "John", "age": 30, "city": "NYC"}
Iteration Behavior:
// Iteration 0: item = {"name": "John"}, index = 0
// Iteration 1: item = {"age": 30}, index = 1
// Iteration 2: item = {"city": "NYC"}, index = 2Accessing Object Data:
// Get the key
{{Object.keys(ctx.nodes.loopNode.outputs.item)[0]}}
// Get the value
{{Object.values(ctx.nodes.loopNode.outputs.item)[0]}}Count-Based Iteration
Execute a specific number of times:
Configuration:
- Type:
FOR - Value:
5or{{ctx.nodes.config.outputs.repeatCount}}
Iteration Behavior:
// Iteration 0: item = undefined, index = 0
// Iteration 1: item = undefined, index = 1
// Iteration 2: item = undefined, index = 2
// Iteration 3: item = undefined, index = 3
// Iteration 4: item = undefined, index = 4String Character Iteration
Iterate over each character in a string:
Configuration:
- Type:
FOR - Value:
"hello"
Iteration Behavior:
// Iteration 0: item = "h", index = 0
// Iteration 1: item = "e", index = 1
// Iteration 2: item = "l", index = 2
// Iteration 3: item = "l", index = 3
// Iteration 4: item = "o", index = 4Loop Execution Flow
Iteration Process
When a Loop node executes:
- Initialize: Index starts at 0, value is evaluated
- Check Condition: Determine if more iterations are needed
- Execute Body: If condition true, execute LOOP-connected nodes
- Increment: Index automatically increments after iteration
- Repeat: Return to step 2 until condition becomes false
- Exit: Execute DEFAULT-connected nodes when loop completes
Context Management
Each iteration maintains:
- Current Index: Available as
{{ctx.nodes.loopNode.outputs.index}} - Current Item: Available as
{{ctx.nodes.loopNode.outputs.item}} - Iteration State: Automatically managed by the execution engine
- Separate Context: Each iteration has isolated input/output context
Advanced Loop Patterns
Conditional Processing
Use loop context in Branch nodes for conditional logic:
// Process only even-indexed items
{{ctx.nodes.loopNode.outputs.index % 2 === 0}}
// Process items meeting criteria
{{ctx.nodes.loopNode.outputs.item.status === "active"}}
// Skip first item
{{ctx.nodes.loopNode.outputs.index > 0}}Data Transformation
Transform each item in a collection:
// Example: Convert array of names to email addresses
// Loop Value: ["john", "jane", "bob"]
// In loop body:
const name = ctx.nodes.loopNode.outputs.item;
const email = `${name}@company.com`;
return email;Batch Processing
Process items in batches using index:
// Process every 10th item
{{ctx.nodes.loopNode.outputs.index % 10 === 0}}
// Create batches
const batchSize = 5;
const currentBatch = Math.floor(ctx.nodes.loopNode.outputs.index / batchSize);Accumulation Patterns
Build results across iterations:
// Collect results (in a non-loop node after completion)
const results = [];
// Results are typically collected in external storage or variables
// accessed after loop completion via DEFAULT connectionLoop Controls and Exit Conditions
Early Exit with Exception
Use Exception nodes within loops for early termination:
// Condition to exit loop early
{{ctx.nodes.loopNode.outputs.item.error !== null}}
// Connect to Exception node to terminate workflow
// or handle error conditionIndex-Based Exit
Control loop execution based on index:
// Limit to first 10 iterations
{{ctx.nodes.loopNode.outputs.index >= 10}}
// Process until specific condition
{{ctx.nodes.loopNode.outputs.index >= ctx.vars.maxIterations}}Integration with Other Nodes
With API Calls
Process each item through an API:
// Loop over user IDs, make API call for each
// Loop Value: [1, 2, 3, 4, 5]
// API URL: https://api.example.com/users/{{ctx.nodes.loopNode.outputs.item}}With Conditional Logic
Use Branch nodes for complex iteration logic:
// Different processing based on item type
{{ctx.nodes.loopNode.outputs.item.type === "premium"}}
// Route to different processing paths
{{ctx.nodes.loopNode.outputs.item.category}}With Data Storage
Store iteration results:
// Build arrays/objects across iterations
// Use workflow variables to accumulate data
// Access final results via DEFAULT connection after loop completionBest Practices
Performance Optimization
- Limit Iterations: Avoid extremely large loops that could impact performance
- Efficient Processing: Keep loop body processing lightweight
- Batch Operations: Consider batch processing for database operations
- Memory Management: Be mindful of memory usage with large datasets
Error Handling
- Validation: Validate loop value before iteration begins
- Error Recovery: Handle errors gracefully within loop body
- Exception Handling: Use Exception nodes for critical failures
- Logging: Log iteration progress for debugging
Design Patterns
- Single Responsibility: Keep loop body focused on one task
- Reusable Logic: Design loop bodies that can be reused
- Clear Naming: Use descriptive names for loop nodes and outputs
- Documentation: Document complex loop logic for maintainability
Data Type Considerations
- Array Validation: Ensure value is actually an array when expected
- Object Structure: Validate object structure for consistent iteration
- Type Checking: Handle mixed data types appropriately
- Null Safety: Check for null/undefined values
Troubleshooting
Common Issues
| Problem | Symptoms | Solution |
|---|---|---|
| Infinite Loop | Workflow never completes | Check loop exit conditions and value type |
| No Iterations | Loop body never executes | Verify value is non-empty array/object or positive number |
| Context Access Error | Cannot access item/index | Check context expression syntax |
| Connection Issues | Wrong nodes executing | Verify LOOP vs DEFAULT connections |
Debugging Techniques
- Test with Small Data: Start with small arrays/low counts
- Check Loop Value: Verify the value evaluates to expected data type
- Validate Connections: Ensure LOOP and DEFAULT connections are correct
- Monitor Context: Check that item/index outputs are accessible
- Review Execution Flow: Trace through iteration logic step by step
Performance Issues
- Large Datasets: Consider pagination or batch processing
- Complex Loop Bodies: Simplify processing logic
- Nested Loops: Avoid deeply nested loop structures
- Resource Usage: Monitor memory and CPU usage
Examples
User Processing Workflow
// Loop Configuration
Type: FOR
Value: {{ctx.nodes.userApi.outputs.users}}
// In loop body - Update user status
URL: https://api.example.com/users/{{ctx.nodes.loopNode.outputs.item.id}}
Method: PUT
Body: {
"status": "processed",
"processedAt": "{{new Date().toISOString()}}",
"batchId": "{{ctx.vars.batchId}}"
}Data Transformation Loop
// Loop Configuration
Type: FOR
Value: {{ctx.nodes.rawData.outputs.records}}
// Transform each record
const record = ctx.nodes.loopNode.outputs.item;
return {
id: record.id,
name: record.fullName?.trim(),
email: record.emailAddress?.toLowerCase(),
createdAt: new Date(record.timestamp).toISOString(),
index: ctx.nodes.loopNode.outputs.index
};Conditional Processing Loop
// Loop Configuration
Type: FOR
Value: {{ctx.nodes.orders.outputs.data}}
// Branch condition - only process paid orders
{{ctx.nodes.loopNode.outputs.item.status === "paid"}}
// In processing branch
const order = ctx.nodes.loopNode.outputs.item;
return {
orderId: order.id,
amount: order.total,
processedIndex: ctx.nodes.loopNode.outputs.index
};Batch Processing with Index Control
// Loop Configuration
Type: FOR
Value: 100 // Process 100 items
// Branch condition - create batches of 10
{{ctx.nodes.loopNode.outputs.index % 10 === 0}}
// In batch processing branch
const batchNumber = Math.floor(ctx.nodes.loopNode.outputs.index / 10);
const itemsToProcess = ctx.vars.allItems.slice(
ctx.nodes.loopNode.outputs.index,
ctx.nodes.loopNode.outputs.index + 10
);