Module 5: Dependencies Between Workflows

1. Introduction: coordinating many workflows

Description

By the end of this lesson you will be able to explain why an automation system with several workflows is more than the sum of its flows, you will know the complete Cumbre system — how order-triage stops being a lone flow and starts coordinating three others — and you will have a clear picture of the three specific disasters that show up when you coordinate badly: cascades, lost ordering, and duplicated effects. You will also get the map of this module's eight lessons, which go from drawing the system to a coordination that survives a piece falling over halfway through.

This matters for a very concrete reason you have already lived if you have ever worked with more than one workflow: the moment one flow calls another, that other one takes too long or fails, and suddenly you do not know whether the work got done, got done halfway, or got done twice. A single workflow, no matter how complex, you can hold entirely in your head. As soon as there are three or four calling each other, questions appear that no individual node answers: in what order do they run? What happens to the other two if the first one fails? Who finds out that one was left halfway done? This module is about those questions.

Connection to the module: this lesson is the setup, not the solution. Here you meet the multi-workflow system you will work on for the eight lessons, you name the three coordination disasters, and you get the map. Lesson 2 gives you the two ways to coordinate — a central director that calls everyone (orchestration) or pieces that react to events with no boss (choreography). Lesson 3 teaches you to draw the graph of who depends on whom. Lessons 4 and 5 tackle two mechanical problems: splitting work without losing items (fan-out/fan-in) and what to do when events arrive faster than they get processed (ordering and backpressure). Lesson 6 is the hinge of the module: the outbox pattern, the technique that makes the whole coordination robust. Lesson 7 takes all of this into the territory of agents that delegate tasks to each other. And lesson 8 pulls it all together in a project: three dependent workflows coordinated so that a mid-way crash does not duplicate or lose anything.

A continuity note before we start. This module assumes you already carry three things from previous modules, and you are going to use them the whole time:

  • Idempotency (Module 2): you know how to make repeating an effect — charging, creating a record, sending an email — not duplicate it, using an idempotency key. Here that tool stops protecting a single workflow and starts protecting coordination across several.
  • Contracts (Module 3): you know that when one workflow calls another, that "calling" is a promise with an input shape and an output shape, validated at the boundary. Here those contracts are the edges of the graph you are going to draw.
  • The data model (Module 4): you have a run ledger — a durable record of which executions already happened — and a deduplication store in Postgres. Here that ledger stops being the memory of one flow and becomes the shared memory of the whole system. It is the piece that, in the end, makes coordination safe.

If any of those three feels shaky, this is a good moment to review it. Everything that follows leans on them.

From a lone workflow to a multi-flow system

In Module 1 we compared a workflow to a bridge over a stream: you build it, you cross it once in the demo, and the serious question is not "does it work?" but "what happens to it when reality hits it?" We are going to stretch that image, because this module changes the scale of the problem.

A single bridge you understand completely. You know where it goes from and to, how much weight it holds, what happens if it rains. Now imagine that instead of a bridge you have a small network of roads in a town: a main road that forks into three, two of those three merge back together further on, and one of them, in a certain stretch, depends on a distant bridge being open. Each road, on its own, you understand. But the town as a system has properties that no individual road has: there are bottlenecks where two roads converge, there is a point where if a bridge goes down three neighborhoods get isolated at once, and there is an order in which it makes sense to clear snow so nothing gets blocked.

That is exactly what happens when you go from one workflow to a system of several. Each flow, on its own, you already know how to build — that is what the foundations guides were about. But the whole system has behaviors that emerge only from how the pieces connect: failure cascades, bottlenecks, effects that fire twice because two flows did the same thing without knowing about each other. Those behaviors do not live in any node. They live in the connections. And this module is about the connections.

Think of it this way: up to now you learned to make each of your flows correct on the inside. This module teaches you to make the system correct, even when each flow by itself already is. Those are two different levels, and the second one does not come free from the first.

The Cumbre system: order-triage is no longer alone

Let's recall Cumbre, the wholesale coffee and tea distributor you met in Module 1. Its central flow is order-triage: it receives every order through a webhook, classifies it with an AI Agent, and registers it in the CRM. Through Module 4, we treated it almost as if it were a lone flow that did all its work in one straight run.

The reality of a growing business is that a single flow ends up being too much. order-triage should not know how to check a customer's credit line, nor how to issue a refund on the payment gateway, nor how to discount inventory in the warehouse system. Each of those is its own domain, with its own rules, and it makes sense for it to live in its own workflow — for the same contract reasons you saw in Module 3: it gets tested separately, versioned separately, reused separately. So Cumbre's real system, the one you are going to coordinate in this module, looks like this:

                          order-triage
                     (Webhook → AI Agent → CRM)
                               │
          ┌────────────────────┼────────────────────┐
          ▼                    ▼                    ▼
    check-credit          issue-refund        inventory-sync
  (checks the           (issues a refund      (discounts stock
   customer's credit     on the gateway)       in the warehouse)
   limit)

Four workflows. One that coordinates — order-triage — and three that do specialized work:

WorkflowWhat it doesWhat kind of operation it is
order-triageReceives and classifies the order, and decides what else needs to happenCoordinator
check-creditChecks whether the customer has available credit for this orderRead (changes nothing)
issue-refundIssues a refund on the payment gatewayEffect: moves money
inventory-syncDiscounts the order's units from inventoryEffect: changes stock

Keep that right-hand column in mind, because it is the same one that organized the whole guide. check-credit is a read: querying it twice gives the same result and does no harm. issue-refund and inventory-sync are effects: issuing two refunds is two refunds, discounting stock twice leaves the warehouse miscounted. All the difficulty of coordinating these four flows comes down to not firing those two effects more times than they should fire.

A Cumbre order still has the same shape you already know, with its order_id as the order's business name:

{
  "event_id": "evt_8f2a91c4",
  "order_id": "ORD-2041",
  "customer_id": "CUST-118",
  "customer_name": "Luna Coffee",
  "amount": 2154.00,
  "currency": "MXN"
}

order_id is going to be the backbone of this whole module. When you coordinate four workflows, the constant question is going to be "has this piece of work, for this order_id, already happened?" And the answer is going to live in the Module 4 ledger.

The three disasters of coordinating badly

When order-triage was a lone flow, its only drama was Module 1's: firing twice and duplicating its own effects. Now that it coordinates three others, three new disasters show up, and they are the three this module exists to prevent. It is worth naming them right away, precisely, because each lesson attacks one or several of them.

Disaster 1 — The cascade

A cascade is when the failure of one workflow drags down the ones that depend on it, and the damage spreads outward like falling dominoes.

Imagine check-credit — the one that checks the customer's credit — gets slow because the bank's system is overloaded. order-triage calls it and sits there waiting. Because order-triage is blocked waiting on check-credit, it cannot handle the next order, which piles up. And the vendor that sends the orders, not getting confirmation from order-triage, starts retrying, which stuffs even more orders into the queue. A single slow service — the bank's — ended up stalling the entire system and multiplying the load. That is a cascade: the problem did not stay where it was born, it spilled over.

Disaster 2 — Lost ordering

Lost ordering is when two events that should be processed in a certain sequence get processed backwards, and the result ends up inconsistent.

A Cumbre customer places an order and, thirty seconds later, modifies it. Two events arrive for the same order_id: first "order of 12 kg," then "correction: it's 8 kg." If your system processes those two events in parallel, or if the second one gets ahead of the first, inventory-sync can end up discounting 12 kg when it should have discounted 8, or applying the correction before the original order and leaving stock in a state that matches neither version. Order mattered, and it got lost. Lesson 5 is devoted entirely to this.

Disaster 3 — The duplicated effect

The duplicated effect is the old acquaintance from Module 1, but now with a new source: it is not only duplicated because a flow runs twice, but because two different flows do the same thing without knowing about each other.

Suppose order-triage decides that a cancelled order needs a refund, and calls issue-refund. Right at that moment, an employee, seeing the same cancellation in the CRM, manually fires another flow that also issues the refund. Two independent paths, one refund owed, two refunds issued. Or more subtly: order-triage calls issue-refund, issue-refund takes a while to respond, order-triage retries the call, and now there are two issue-refund executions in flight for the same order. In a single-flow system you learned to protect yourself from your own double firing. In a multi-flow system, the double firing can come from a neighboring flow.

And there is something worse worth anticipating: the three disasters feed each other. A cascade, by stalling the system, makes the vendor retry, which multiplies the triggers — and those duplicated triggers, under load, arrive out of order. That is, you start with one slow piece (cascade), and end up with duplicated, out-of-order events (the other two disasters) as a consequence. You rarely face just one; in production, a real incident is usually all three tangled together. That is why patching each one separately is not enough: you need a design that prevents them at the root.

These three disasters have something in common, and it is the good news: all of them get solved with the same two ideas you already carry — idempotent effects and a durable shared memory (the ledger) — plus one new pattern that ties them together, the outbox from lesson 6. You are not going to learn three different solutions for three problems. You are going to learn to apply what you already know at the system level. That economy — few ideas, well combined, against many symptoms — is the mark of a good design, and it is what makes this module, even though it covers a lot of ground, rest on a handful of principles you already know.

The piece that changes everything: the ledger as shared memory

Before listing the module's promise, I want to give you a preview of the idea that makes everything else possible, because it is going to give meaning to every lesson. It is the reuse of something you already built.

In Module 4 you set up a run ledger: a table in Postgres where the system records which executions have already happened, so it can detect a duplicate trigger. In that module, the ledger was the memory of one workflow: order-triage recorded "I already processed order ORD-2041" so it would not process it again if the webhook fired twice.

This module's move is simple to state and powerful in its consequences: that same ledger, shared by the four workflows, becomes the memory of the entire system. Not of one flow. Of all of them.

Think of it as the whiteboard in a restaurant kitchen. In a well-run kitchen there is a whiteboard where finished dishes get marked off. Any cook, before starting a dish, looks at the board: if table 4's dish is already crossed off, they do not prepare it again, even if the waiter asks for it a second time by mistake. The board does not belong to any one cook; it belongs to the kitchen, and its value is precisely that everyone reads it and everyone writes to it. Without it, two cooks can prepare the same dish without knowing. With it, work already done is visible to everyone.

The ledger is that whiteboard. When issue-refund is about to issue a refund for ORD-2041, it first checks the ledger: "has this order's refund already been issued?" If yes, it does not issue it again. When it issues it, it records it. And because the ledger is shared, if another flow — or a second execution of the same one — asks the same thing a second later, it sees it is already done. Disaster 3's duplicated effect is prevented because work done by one flow is visible to all the others.

This idea — a durable, shared memory against which every effect is checked before it runs — is the thread that stitches together the whole module. The dependency graph (lesson 3) tells you who reads the board; the outbox pattern (lesson 6) gives you the disciplined way to write to it without losing or duplicating anything; delegation between agents (lesson 7) uses the board so two agents do not do the same work. It all points to the same place. If at any point in the module you feel lost, come back to this image: the kitchen whiteboard that everyone reads before acting.

What this module promises you

By the end of the eight lessons you will be able to take a multi-workflow system — Cumbre's four, or the ones you have at your job — and:

Draw its dependency graph. A diagram of who calls whom, with what kind of connection, and what propagates if a piece fails. It sounds simple and it is the tool that will save you the most times: half of coordination bugs are visible at a glance in the graph, before you write a single line.

Choose how to coordinate. You will know when a central director calling each piece in order makes sense, and when pieces reacting to events with no director makes sense. It is not an aesthetic preference: each option has a different cost in visibility, coupling, and resistance to failure.

Coordinate without duplicating. With the outbox pattern and the ledger, you will be able to make a mid-chain crash across workflows not leave the system with a lost effect or a duplicated effect. It is the module's core capability.

Delegate between agents safely. When an AI Agent hands work off to another — as you saw in the chatbots guide — you will be able to guarantee that no agent repeats an effect another one already did, using the ledger as shared memory and iteration limits as a brake. It is the same coordination as always, applied to actors that reason instead of to fixed nodes, and therefore more delicate.

This module's map

The eight lessons go from the drawing to the practice. Pay attention to the order, because each block leans on the previous one:

LessonWhat it solves
2The two ways to coordinate: orchestration (one director calls everyone) vs. choreography (each piece reacts to events). Advantages, risks, and when each one fits.
3How to draw the dependency graph of a real system: who triggers whom, where there are cycles, and how far a failure propagates.
4Fan-out and fan-in: splitting work into several branches or sub-executions and joining them back together without losing or duplicating items. The risk of a partial retry.
5Ordering and backpressure: what happens when events arrive faster than they get processed, and how n8n's queue mode gives you capacity and pace control.
6The outbox pattern: separating "deciding the effect" from "executing the effect," so a failure between steps does not duplicate or lose anything. The module's central technique.
7Delegation between agents: how two agents passing tasks to each other avoid firing the same effect twice or falling into a loop.
8The project: coordinating check-credit, issue-refund, and inventory-sync with a director, an outbox, and an idempotent executor, and proving that a mid-way crash neither duplicates nor loses effects.

The progression has a logic to it: first the two ways to coordinate (2), then the tool to see them — the graph (3), then the two mechanical problems of splitting and of pace (4 and 5), then the pattern that resolves coordination (6), then its application to agents (7), and finally the hands-on work that ties it all together (8). By the time you finish, coordinating several workflows will stop giving you that "I'm not quite sure what's happening in there" feeling and become something you can draw, reason about, and test.

A note on scope

This module designs the correctness of coordination: that the system does no harm even if a piece fails, repeats, or lags. It does not cover operating it at production scale — standing up a cluster of queue-mode workers, sizing Redis, monitoring inter-workflow latency on a dashboard. That is the work of the production and maintenance guide, and the boundary is stated explicitly at the end of Module 6. When we talk about queue mode in lesson 5, we are going to treat it as the mechanism that provides capacity and pace control, not as an infrastructure configuration exercise. You will understand what it is and why it matters for ordering; tuning it for a thousand orders a minute is a different guide.

The lab and a note on dates

Starting in lesson 4 you are going to build for real, and everything runs at zero cost on the same self-hosted Community instance with the Module 4 Starter Kit — n8n plus a local Postgres. You do not need paid services or a credit card: the ledger, the outbox, and the simulated effects all live in your own Postgres. If you got here following the guide, you already have it set up; if you skipped Module 4, that is where it gets built piece by piece.

And an honesty worth stating right away, in the spirit that any dated fact ages: the exact names of some n8n nodes and options change between versions. This guide was written with n8n 2.x in mid-2026. Whenever an exact name matters — the option that makes an Execute Sub-workflow wait for the result, the node that joins branches, queue mode's variables — I am going to flag it and ask you to verify the label in your own panel and in the official documentation. The concept does not change; a button's text sometimes does. Noting the version you use is a habit that pays off: when something in the guide does not match your screen, the first question is always "what version am I on?"

Common mistakes

Believing that if each workflow works, the system works (conceptual). What happens: someone tests order-triage, tests check-credit, tests issue-refund and inventory-sync, each one separately with a happy-path case, sees all four green, and concludes the system is ready. In production a duplicated charge shows up that none of the four flows, looked at individually, explains. Why it happens: coordination disasters do not live inside any flow, they live in how the flows connect — in what happens when order-triage retries issue-refund, or when two events for the same order run at the same time. Testing the pieces separately never tests that. How to detect it: ask yourself "what exactly did I test?" If the answer is "that each workflow processes a correct input," you did not test coordination. How to fix it: the tests that matter in this module are the seam tests — fire order-triage twice in a row, kill issue-refund halfway through, send two events for the same order_id — and those are exactly the ones the lesson 8 project builds.

Cramming everything into one giant workflow to "avoid having to coordinate" (conceptual). What happens: to avoid the complexity of several flows, someone puts the credit check, the refund, and the inventory discount inside order-triage, all in one single chain of nodes. Why it happens: a single flow seems simpler to understand and has no "connections" that can fail. How to detect it: if a change to the refund logic forces you to open, understand, and put at risk the same flow that also receives orders and discounts inventory, your flow is doing too much. How to fix it: splitting by domain is the right call — each piece gets tested, versioned, and reused separately, as Module 3 taught — what you need to learn is not to avoid coordination, but to make it safe, which is exactly what this module is about. The monolith does not eliminate the disasters, it just hides them inside a flow where they are harder to see.

Assuming that "calling another workflow" is instant and always works (conceptual). What happens: coordination gets designed as if order-triage called issue-refund and the result came back instantly, without accounting for the call possibly taking a while, failing halfway, or coming back after order-triage has already given up. Why it happens: in the demo, with everything local and fast, calls between workflows are nearly instant and always succeed, so the possibility of failure does not feel real. How to detect it: for every arrow in your dependency graph, ask "what happens if this call takes ten seconds?" and "what happens if it never comes back?" If you have no answer, that is a fragile point. How to fix it: treating every call between workflows as what it is — an operation that can fail, take a while, or repeat — is the mindset of the whole module, and the outbox pattern from lesson 6 is the tool that makes it concrete.

Exercises

Exercise 1 — Classify the four workflows. Without looking back at this lesson's table, write down which of Cumbre's four workflows — order-triage, check-credit, issue-refund, inventory-sync — are reads and which are effects, and for each effect say what concrete damage it would cause if it ran twice for the same order.

See solution

check-credit is a read: it checks the customer's available credit and changes nothing. Querying it twice gives the same answer and does no harm.

issue-refund and inventory-sync are effects. If issue-refund runs twice for the same order, it issues two refunds: the customer gets back double what they were owed, or gets refunded something that had already been refunded. If inventory-sync runs twice, it discounts double the units: the warehouse ends up with lower stock than reality, and eventually the system rejects orders for product that actually exists.

order-triage is the coordinator: its job is less about an effect of its own and more about deciding which effects to fire. Its duplication is dangerous precisely because, running twice, it can fire the other two's effects twice.

Why this works: you just identified where the system's real danger lies. Everything that follows in the module is about protecting those two effects — issue-refund and inventory-sync — from firing more times than they should, no matter which of the three disasters the threat comes from.

Exercise 2 — Match the disaster to the scene. For each of these three scenes, say which of the three disasters it is — cascade, lost ordering, or duplicated effect — and justify it in one sentence:

(a) The bank's system gets slow, check-credit hangs, order-triage stops handling orders, and the vendor starts retrying, saturating everything. (b) A customer orders 12 kg and corrects it to 8 kg thirty seconds later; the two events get processed in parallel and inventory-sync ends up discounting 12. (c) order-triage calls issue-refund, does not get a response in time, retries, and two issue-refund executions end up issuing the same refund.

See solution

(a) Cascade. The failure was born in one service (the bank) and propagated outward: it hung check-credit, then order-triage, and ended up saturating the entry point. The damage did not stay where it started.

(b) Lost ordering. The two events for the same order had a correct sequence — first the order, then the correction — and got processed backwards or in parallel, leaving stock in a state that matches neither version of the order.

(c) Duplicated effect. One refund owed, two executions issuing it, because of a retry that did not know the first call was still in flight. It is the same damage as Module 1, but triggered by coordination between two flows.

Why this works: recognizing which disaster it is is the first step toward knowing which tool to apply. The cascade gets attacked with ordering and backpressure (lesson 5) and with decoupling (lesson 2); lost ordering, with lesson 5; the duplicated effect, with idempotency and the outbox (lessons 6 and 7). Naming the problem is half the solution.

Exercise 3 — Draw a system you know. Think of some real system you use or have used — an e-commerce site, a booking system, the onboarding flow at your job — and try to draw, with boxes and arrows, what "workflows" or processes make it up and who depends on whom. It does not have to be exact. Mark at least one place where you think a failure would propagate to others.

See solution

There is no single answer, and that is the point: almost any real system, when you draw it, turns out to be several dependent pieces rather than one. A typical example, employee onboarding: a central "onboarding" process that triggers creating the email account, registering in the payroll system, assigning equipment, and sending a welcome email. The classic propagation point is that the welcome email depends on the email account already existing: if creating the account fails or is slow, the welcome email bounces or gets sent to an address that does not work yet.

If you managed to mark a point where a failure propagates, you already did, on a small scale, what lesson 3 formalizes: finding in the graph the place where one downed piece drags others down with it. That instinct — looking at a system and asking yourself "what falls if this falls?" — is exactly the system-owner mindset the whole guide cultivates.

Summary and next step

In this lesson you made the leap from a lone workflow to a system of several dependent flows. You saw that order-triage is no longer alone: it coordinates check-credit (a read), issue-refund (an effect that moves money), and inventory-sync (an effect that changes stock). And you precisely named the three disasters that show up when coordinating badly: the cascade (a failure that propagates), lost ordering (events processed backwards), and the duplicated effect (two flows doing the same thing without knowing it). The good news that closes the lesson is that all three get solved with what you already carry — idempotent effects (Module 2) and a durable shared memory, the ledger (Module 4) — plus the outbox pattern you will learn in lesson 6.

Before moving on to lesson 2 you should be able to: name Cumbre's four workflows and say which are reads and which are effects; describe each of the three coordination disasters in one sentence; and explain why testing each workflow separately does not prove the system is sound.

What comes next is the first design decision of any multi-flow system: does a central director coordinate them by calling them in order, or does each piece react on its own to the events that matter to it? Lesson 2 puts those two forms — orchestration and choreography — side by side, with their advantages and risks, and gives you the criteria for choosing. It is the decision that will shape everything else.

Resources

  • Execute Sub-workflow node — n8n Docs — the node with which one workflow calls another and waits for its result. It is the main edge of the dependency graph you are going to draw in lesson 3; worth keeping in view from here on.
  • Execute Sub-workflow Trigger — n8n Docs — the trigger on the called workflow's side, where the input contract you saw in Module 3 gets declared.
  • Sub-workflows — n8n Docs — the overview of why and how a system gets split into several workflows that call each other; this module's conceptual starting point.
  • Release notes 2.x — n8n Docs — the n8n 2.x release history; useful for confirming which version you are on against what this guide describes, because some node names change between minor versions.