Tips > Building Workflows

Break Large Workflows into Sub-Workflows

When a workflow exceeds approximately 20 nodes, it becomes difficult to read, debug, and modify safely.

TipAdvanced2 min read

When a workflow exceeds approximately 20 nodes, it becomes difficult to read, debug, and modify safely. Split it into smaller sub-workflows, each handling a single responsibility. The parent workflow orchestrates the sub-workflows using the Execute Sub-Workflow node, passing data in and receiving results back. This mirrors the function decomposition principle from software engineering.

Real-world example: A monolithic "Order Processing" workflow with 45 nodes handles: order validation, inventory check, payment processing, shipping label generation, and customer notification. Refactored into sub-workflows:

Parent workflow: "Orders - Process New Order"

[Webhook: New Order]
    → [Execute Sub-Workflow: "Orders - Validate"]
    → [IF: valid]
        → [Execute Sub-Workflow: "Inventory - Reserve Stock"]
        → [Execute Sub-Workflow: "Payments - Charge Customer"]
        → [Execute Sub-Workflow: "Shipping - Generate Label"]
        → [Execute Sub-Workflow: "Notifications - Order Confirmation"]
```text
Each sub-workflow definition:

```text
"Orders - Validate" (6 nodes)
  Input:  order object
  Output: { valid: boolean, errors: string[] }

"Inventory - Reserve Stock" (8 nodes)
  Input:  line_items array
  Output: { reserved: boolean, warehouse_id: string }

"Payments - Charge Customer" (5 nodes)
  Input:  { customer_id, amount, currency }
  Output: { charge_id, status }

"Shipping - Generate Label" (7 nodes)
  Input:  { address, items, warehouse_id }
  Output: { tracking_number, label_url }

"Notifications - Order Confirmation" (4 nodes)
  Input:  { customer_email, order_summary, tracking_number }
  Output: { sent: boolean }
```text
> **Note: Data Passing**
>
> Sub-workflows receive the output of the node connected to the Execute Sub-Workflow trigger. Return data from the sub-workflow using the last node's output. Keep interfaces (inputs/outputs) small and well-defined -- pass only the data each sub-workflow needs.

The refactored system is easier to test (run each sub-workflow independently), debug (failures point to a specific sub-workflow), and modify (change shipping logic without touching payment code).

**Related:** [Always Set an Error Workflow on Every Production Workflow](../error-handling-and-reliability/01-always-set-an-error-workflow-on-every-production-workflow.md) | [Use "Pin Data" to Freeze Node Output](../testing-and-debugging/01-use-pin-data-to-freeze-node-output.md)

Want this running in your stack?

I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.