Make.com Patterns
Scenarios, modules, and the anatomy of a flow
Make.com (formerly Integromat) automates work by connecting modules — each one an action against an app's API — into a scenario, a visual flow that runs when triggered. A trigger module (a new form submission, a scheduled interval, a webhook call) starts the run; every module after it receives the output (called the bundle) of the module before it.
What separates Make from simpler tools like Zapier is that it exposes the actual data structure flowing between modules, and gives you real control-flow primitives — iterators, aggregators, routers, and error handlers — instead of a strictly linear step list. Those four primitives are what this lesson covers, because they're what separate a fragile one-off automation from one that survives real-world data.
Iterators: flattening arrays into individual bundles
Many API responses return an array — a form with repeatable fields, a list of order line items, a batch of new CRM records. An Iterator module takes an array and emits one bundle per array item, so every module downstream of it runs once per item instead of once per original bundle.
The pattern shows up constantly: a webhook delivers an order with multiple line items, you Iterate over the items array, and each iteration creates one row in a spreadsheet or one line item in an accounting system. Without the Iterator, you'd receive the whole array as a single opaque bundle and have no way to act on each item individually.
Iterators multiply your operations count
Aggregators: the inverse operation
An Aggregator does the opposite of an Iterator — it collects multiple incoming bundles and combines them back into a single array or a single text block. The most common use: iterate over CRM contacts matching a filter, then aggregate the results into one summary email or one Slack message instead of sending N separate notifications.
Aggregators need a defined source module — the specific Iterator (or any module producing multiple bundles) whose output it should collect. Get the source wrong and the Aggregator either collects nothing or collects far more than intended, because it aggregates every bundle since the last aggregation boundary.
Webhook (order.created)
-> Iterator (order.items[])
-> Filter (item.price > 100)
-> HTTP: POST to fulfillment API
-> Array Aggregator (source: Iterator)
-> Slack: "Order #{{order.id}} processed, {{length(items)}} high-value items"
# The Aggregator runs once per original webhook call, not once per item —
# it re-collapses the fan-out the Iterator created.Routers: branching one flow into many
A Router splits a scenario into multiple parallel paths, each with its own filter. Unlike a simple if/else, every route with a filter that evaluates true actually runs — routes aren't mutually exclusive by default, so a bundle can flow down two or more branches simultaneously if two filters both match.
This is the standard tool for "do different things depending on data" logic: a lead-routing scenario might route enterprise-tier leads to a Slack alert and a CRM task, while routing self-serve leads to only an autoresponder email — two branches, two different filter conditions, running off the same trigger.
Order your routes from most to least specific
Error handling: the difference between a demo and production
Every module in Make can have an error handler attached — a mini-branch that runs only if that specific module fails, instead of the scenario silently halting. The four handler types cover different recovery strategies:
- Resume — supplies a fallback value and continues the scenario as if the module succeeded
- Ignore — skips the failure and moves to the next module with no output from the failed one
- Rollback — reverts any commits made in that execution (relevant for modules with transactional support) and stops
- Break — stops the current execution but automatically retries later, useful for transient failures like rate limits or timeouts
A scenario with no error handlers isn't more reliable — it just fails invisibly. The first time an upstream API changes its response shape or briefly returns a 500, the whole scenario silently stops with no one aware.
HTTP: GET enrichment API
[Error Handler: Break]
-> Wait 5 minutes -> Retry HTTP module
[Error Handler: Resume, fallback = {"company": "Unknown"}]
-> continues scenario with placeholder data instead of halting
# Break is right for rate limits (5xx, 429) — the request will likely
# succeed on retry. Resume is right when partial data is acceptable
# and blocking the whole scenario on one enrichment call isn't worth it.Filters vs. routers vs. error handlers — choosing the right tool
These three control-flow mechanisms are easy to conflate. A Filter (attached to a single connection between two modules) stops a bundle from proceeding if a condition isn't met — use it for simple gating. A Router is for branching one input into multiple independent downstream paths. An Error Handler is specifically for recovering from a module *failing*, not for normal conditional logic — routing a "declined" payment status through an error handler (when the API call itself succeeded and just returned that status) is a common modeling mistake; that's a Filter/Router case, not an error case.
Data structures and the mapping panel
Every module's output becomes a structured bundle you can reference in every downstream module via Make's mapping panel — click any field in a later module and you're offered every available field from every prior module in the chain, not just the immediately preceding one. This is what makes Make's flows debuggable: you can inspect the exact bundle shape at each step of a real execution in the execution history, which is invaluable when a scenario that worked in testing starts failing against production data with an unexpected null or a differently-shaped array.
What's next
Iterators, aggregators, routers, and error handlers are the vocabulary for building automation that survives contact with messy real-world data instead of breaking on the first edge case. The same control-flow thinking applies directly to open-source alternatives like n8n, and to the server-side tagging pipelines covered next.
Next: Server-Side GTM →
I build these systems professionally.
Whether it's a RAG pipeline, analytics migration, or AI workflow — let's talk.