Guide · Make.com · Bundles and arrays

Make.com iterator vs. aggregator: when to use which (with examples)

The iterator and the aggregator are opposites, and mixing them up is behind many "why did I get 40 emails" and "why is only the last row saved" questions. This guide explains what each one does to your data, then builds one example scenario that uses both.

By Flowpaja · Published

An order with an items array, an iterator producing two bundles that each add a Google Sheets row, and an aggregator merging them into one bundle so Gmail sends one email
The iterator splits the array into one bundle per item; the aggregator merges them back, so the email goes out once.
Disclosure: everything in this guide works with plain Make.com and the apps it connects. At the end we mention our own Make templates and our Make scenario fix service on Fiverr. Module names, settings and limits were checked against Make's aggregator docs and Tools docs in October 2026. Menus and limits change, so check them if something looks different.

What you need

  • A Make.com account
  • Some data that contains a list, such as an order with line items, a set of rows from Google Sheets or the attachments of an email
  • Google Sheets and Gmail connections if you want to follow the example

The idea in one paragraph

Make passes data between modules as bundles. Most modules take one bundle and return one bundle. An iterator takes one bundle that contains an array and turns each item into its own bundle: one in, many out. An aggregator does the reverse: it takes many bundles and merges them into one: many in, one out. Everything between the two runs once per item, so the position of these modules decides how many times a module runs, and how many credits you use.

Step-by-step: build one scenario that uses both

The example: an order arrives with several line items. You want one row in Google Sheets per item, then one email to the customer with the total and a list of what they ordered.

1. Get data that contains an array

Start with a trigger that delivers an order, such as Webhooks – Custom webhook, or an HTTP – Make a request that returns JSON. A sample payload looks like this:

{"order_id": "A-1001", "email": "[email protected]",
 "items": [{"name": "Desk lamp", "qty": 2, "price": 19.5},
           {"name": "Cable", "qty": 3, "price": 4}]}

After a Run once, Make shows items as an array in the output.

2. Add Flow Control – Iterator

In the Array field, map items. Run once and look at the output: you now see one bundle per item, each with name, qty and price. The module count in the bubble shows two bundles. Everything you add after this point runs twice for this order.

3. Do something per item

Add Google Sheets – Add a Row. Map Order ID from the trigger (still available, since it comes earlier in the scenario) and Name, Qty and Price from the iterator. Two rows are added.

4. Close the loop with an aggregator

Now you need a single result again. Add Tools – Numeric aggregator. Set the source module to the Iterator. For Function choose Sum, and for Value use:

{{2.qty * 2.price}}

The aggregator waits for all the bundles from its source, then emits one bundle with the total. Use Tools – Text aggregator the same way for the list of items. Source module: the iterator. Text: {{2.qty}} x {{2.name}}, with a new line as the row separator.

5. Use the aggregated result

After the aggregator, add Gmail – Send an email. To is {{1.email}} from the trigger. Body contents can use the aggregator's result, for example "Your total: {{4.result}}". Because the aggregator produced one bundle, Gmail runs once, not twice.

6. Know when you don't need an iterator at all

Make has functions that work on arrays directly. If all you need is the number of items, {{length(1.items)}}. To join names in a line, {{join(map(1.items; "name"); ", ")}}. To add up one field, {{sum(map(1.items; "price"))}} (that sums the prices as they are, not quantity times price). These run inside a module you already have, with no loop and no extra credits. Use an iterator when each item needs its own module action, such as its own row, its own file upload or its own Slack message.

Quick guide: which tool?

You want toUse
Do something once per item in a listIterator
Turn many bundles into one listArray aggregator
Build one block of text, such as an email bodyText aggregator
Add up or count valuesNumeric aggregator
Just read or reshape an array in one placemap(), join(), sum() and length()

The Iterator and the Array aggregator are under Flow Control; the Text and Numeric aggregators are under Tools.

Common errors and fixes

You get one email per item instead of one in total. The Gmail module sits inside the loop, between the iterator and the aggregator or after the iterator with no aggregator. Add the aggregator and put Gmail after it.

Only the last item is saved, or the aggregator returns just one value. Usually the source module is set wrongly, or the aggregation is being done by a Set variable module that overwrites itself each time. Make sure the aggregator's source module is the iterator or the search that produces the bundles.

The iterator outputs nothing or reports that it expected an array. The field you mapped is not an array: it is text, a single object or empty. Check the output of the previous module. If you have a comma-separated text, split it first (for example with the split() function) and iterate the result.

The scenario carries on even though the search found nothing. That is expected when an aggregator follows the search: by default it outputs one bundle even when no bundles reach it, which is useful for handling "not found" cases. To stop instead, switch on Stop processing after an empty aggregation in the aggregator's advanced settings, or add a filter after it, for example when the aggregated text is empty.

You can't see earlier items' data after the aggregator. After aggregation you have the aggregated result and anything from modules before the loop. Per-item values from inside the loop are gone, unless you aggregated them into an array.

Credit usage is much higher than expected. Every module after an iterator runs once per item. A list of 100 rows through four modules uses many more credits than the same job done with map() inside one module. The History tab shows the real numbers for each run.

FAQ

Can I have an iterator inside an iterator?
Yes, if each item contains its own array. Each loop you want to merge back needs its own aggregator, and credit usage multiplies, so keep an eye on it.
What is the Array aggregator for?
It collects bundles into an array you can pass on, for example to an HTTP request that expects a JSON list, or to count results with length().
Which comes first, the iterator or the aggregator?
Usually the iterator opens a loop and the aggregator closes it. But an aggregator can also follow a search module with no iterator at all, because the search already returns several bundles.
Does the aggregator have to be right after the iterator?
No. The modules between them run once per item. The aggregator's source module setting is what ties them together.

Want a second pair of eyes on your loops?

If a scenario sends one email per item or uses far more credits than expected, send the exported blueprint and a description of the problem to our Make scenario fix service on Fiverr, no logins needed. Our Make.com templates cover invoice reminders, quote follow-ups and form leads. Running a Shopify store? Our Shopify orders to Google Sheets and Slack setup on Fiverr builds this kind of order flow for you, from $80.

Stuck on an error in your own Make scenario? Make scenario fix / debugging on Fiverr, from $25: send the exported blueprint and a description of the error, no logins needed.

← All guides · All templates

Google, Gmail, Google Sheets, Google Drive, Typeform and Make are trademarks of their owners. Flowpaja is independent and not affiliated with or endorsed by them. Menus and features change; check the providers' current help.