Skip to main content

Multi-Node Workflow Example

This example demonstrates a complex workflow with multiple execution branches, parallel processing, conditional routing, and data merging. Perfect for advanced automation scenarios.

Workflow Overview

The workflow implements a data enrichment pipeline:
  1. Webhook Trigger - Receives batch data requests
  2. Split In Batches - Processes items individually
  3. IF Node - Routes based on data type
  4. Parallel Processing - Multiple API calls simultaneously
  5. Merge Node - Combines enriched data
  6. Set Node - Final formatting
  7. Respond to Webhook - Returns processed results

Use Cases

  • Data enrichment pipelines
  • Multi-source data aggregation
  • Parallel API processing
  • Complex business logic workflows
  • ETL (Extract, Transform, Load) operations

Complete Workflow JSON

{
  "name": "Multi-Node Data Pipeline",
  "nodes": [
    {
      "id": "webhook-1",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [250, 400],
      "parameters": {
        "httpMethod": "POST",
        "path": "enrich-data",
        "responseMode": "lastNode",
        "options": {}
      },
      "webhookId": "data-enrichment"
    },
    {
      "id": "split-1",
      "name": "Split In Batches",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [450, 400],
      "parameters": {
        "batchSize": 5,
        "options": {}
      }
    },
    {
      "id": "if-1",
      "name": "Route By Type",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [650, 400],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "condition-1",
              "leftValue": "={{$json.type}}",
              "rightValue": "user",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "http-user-1",
      "name": "Fetch User Data",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [850, 300],
      "parameters": {
        "method": "GET",
        "url": "https://api.example.com/users/{{$json.id}}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Request-ID",
              "value": "={{$workflow.id}}-{{$runIndex}}"
            }
          ]
        },
        "options": {
          "timeout": 10000,
          "retry": {
            "maxRetries": 3,
            "retryInterval": 1000
          }
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "API Auth"
        }
      }
    },
    {
      "id": "http-metadata-1",
      "name": "Fetch Metadata",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [850, 400],
      "parameters": {
        "method": "GET",
        "url": "https://api.example.com/metadata/{{$json.id}}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 10000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "API Auth"
        }
      }
    },
    {
      "id": "http-company-1",
      "name": "Fetch Company Data",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [850, 500],
      "parameters": {
        "method": "GET",
        "url": "https://api.example.com/companies/{{$json.id}}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 10000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "1",
          "name": "API Auth"
        }
      }
    },
    {
      "id": "merge-1",
      "name": "Merge Data Sources",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [1050, 400],
      "parameters": {
        "mode": "combine",
        "combinationMode": "mergeByPosition",
        "options": {}
      }
    },
    {
      "id": "set-1",
      "name": "Format Enriched Data",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [1250, 400],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "assign-1",
              "name": "id",
              "value": "={{$json.id}}",
              "type": "string"
            },
            {
              "id": "assign-2",
              "name": "type",
              "value": "={{$json.type}}",
              "type": "string"
            },
            {
              "id": "assign-3",
              "name": "enriched",
              "value": "={{{
  user: $('Fetch User Data').item?.json,
  metadata: $('Fetch Metadata').item?.json,
  company: $('Fetch Company Data').item?.json
}}}",
              "type": "object"
            },
            {
              "id": "assign-4",
              "name": "processed_at",
              "value": "={{$now}}",
              "type": "string"
            },
            {
              "id": "assign-5",
              "name": "status",
              "value": "completed",
              "type": "string"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "loop-1",
      "name": "Loop Over Batches",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [1450, 400],
      "parameters": {
        "batchSize": 5,
        "options": {}
      }
    },
    {
      "id": "aggregate-1",
      "name": "Aggregate Results",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [1650, 400],
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      }
    },
    {
      "id": "respond-1",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [1850, 400],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{{
  total_processed: $json.length,
  results: $json,
  workflow_id: $workflow.id,
  execution_time: $executionTime
}}}",
        "options": {}
      }
    }
  ],
  "connections": {
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Split In Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split In Batches": {
      "main": [
        [
          {
            "node": "Route By Type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route By Type": {
      "main": [
        [
          {
            "node": "Fetch User Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Metadata",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch Company Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch User Data": {
      "main": [
        [
          {
            "node": "Merge Data Sources",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Metadata": {
      "main": [
        [
          {
            "node": "Merge Data Sources",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Fetch Company Data": {
      "main": [
        [
          {
            "node": "Merge Data Sources",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Data Sources": {
      "main": [
        [
          {
            "node": "Format Enriched Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Enriched Data": {
      "main": [
        [
          {
            "node": "Loop Over Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Batches": {
      "main": [
        null,
        [
          {
            "node": "Split In Batches",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Aggregate Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Results": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false
}

Architecture Overview

Webhook → Split Batches → Route by Type
                              |
                              |-- User Type → [Fetch User + Fetch Metadata] → Merge
                              |                                                  |
                              |-- Company Type → [Fetch Company + Fetch Metadata] → Merge
                                                                                      |
                                                                        Format → Loop → Aggregate → Respond

Step-by-Step Breakdown

1

Batch Processing Setup

The Split In Batches node processes items in groups of 5 to prevent overwhelming external APIs.Benefits:
  • Memory efficient for large datasets
  • Respects rate limits
  • Progress tracking
  • Can resume on errors
2

Conditional Routing

The IF node routes data to different processing branches based on type.Routes:
  • TRUE branch (type=“user”) → User + Metadata API calls
  • FALSE branch (other types) → Company + Metadata API calls
3

Parallel API Calls

Multiple HTTP nodes execute simultaneously within each branch:
  • User branch: 2 parallel calls
  • Company branch: 2 parallel calls
Performance: 2x faster than sequential processing
4

Data Merging

The Merge node combines results from parallel API calls.Mode: Combine by position (preserves order)
  • Input 0: Primary data (User or Company)
  • Input 1: Metadata
5

Data Formatting

The Set node structures the enriched data into a consistent format using n8n expressions to reference multiple node outputs.
6

Batch Loop & Aggregation

The Loop node returns to process next batch, then Aggregate collects all results into final response.Output: Single array with all processed items

Advanced Patterns Explained

Parallel Execution

When an IF node has multiple connections on one output, they execute in parallel:
"Route By Type": {
  "main": [
    [
      {"node": "Fetch User Data"},
      {"node": "Fetch Metadata"}  // Executes simultaneously
    ]
  ]
}

Cross-Node References

The Set node accesses data from multiple previous nodes:
$('Fetch User Data').item?.json    // Access specific node output
$('Fetch Metadata').item?.json     // Optional chaining prevents errors
Important: Use $('Node Name') syntax to reference specific nodes. The ?. optional chaining prevents errors when a branch didn’t execute.

Batch Loop Pattern

The Loop Over Batches node has three outputs:
  1. Output 0 (null) - Not used
  2. Output 1 - Loop back to continue processing
  3. Output 2 - Final output when all batches complete

Expected Response

{
  "total_processed": 4,
  "results": [
    {
      "id": "user-123",
      "type": "user",
      "enriched": {
        "user": {"name": "John Doe", "email": "[email protected]"},
        "metadata": {"created_at": "2024-01-15", "updated_at": "2024-03-10"},
        "company": null
      },
      "processed_at": "2024-03-15T10:30:00.000Z",
      "status": "completed"
    },
    {
      "id": "company-456",
      "type": "company",
      "enriched": {
        "user": null,
        "metadata": {"created_at": "2023-05-20", "updated_at": "2024-03-10"},
        "company": {"name": "Acme Corp", "industry": "Technology"}
      },
      "processed_at": "2024-03-15T10:30:01.000Z",
      "status": "completed"
    }
  ],
  "workflow_id": "wf-12345",
  "execution_time": "2.3s"
}

Performance Optimization

Adjust Batch Size

For faster processing with good APIs:
{"batchSize": 10}  // Process 10 items at once
For rate-limited APIs:
{"batchSize": 3}  // Smaller batches, more requests

Add Retries

All HTTP nodes include retry configuration:
{
  "options": {
    "retry": {
      "maxRetries": 3,
      "retryInterval": 1000
    }
  }
}

Add Rate Limiting

Insert a Wait node to control request rate:
{
  "name": "Rate Limit",
  "type": "n8n-nodes-base.wait",
  "parameters": {
    "amount": 100,
    "unit": "ms"
  }
}

Common Modifications

Add More Route Types

Extend the IF node conditions:
{
  "conditions": [
    {"leftValue": "={{$json.type}}", "operator": "equals", "rightValue": "user"},
    {"leftValue": "={{$json.type}}", "operator": "equals", "rightValue": "admin"}
  ],
  "combinator": "or"
}

Add Database Storage

Insert after Format Enriched Data:
{
  "name": "Save to Database",
  "type": "n8n-nodes-base.postgres",
  "parameters": {
    "operation": "insert",
    "table": "enriched_data"
  }
}

Add Error Handling

See Error Handling Example for comprehensive patterns.

Debugging Tips

1

Enable Save Execution Data

In workflow settings:
{
  "saveDataSuccessExecution": "all",
  "saveDataErrorExecution": "all"
}
2

Add Debugging Nodes

Insert Set nodes to inspect data:
{
  "name": "Debug Point",
  "parameters": {
    "assignments": {
      "assignments": [
        {"name": "debug_data", "value": "={{$json}}"},
        {"name": "node_name", "value": "={{$node.name}}"},
        {"name": "run_index", "value": "={{$runIndex}}"}
      ]
    }
  }
}
3

Monitor Performance

Use execution time metadata:
  • Check $executionTime in final node
  • Review execution logs
  • Track batch processing times

Next Steps

Build docs developers (and LLMs) love