Skip to Content
đź›  Buildđź›  Action StepsLoops & IterationRepeater

Repeater

Repeater repeats a body of steps: look the customer up, decide something, write it back, then round again. It runs once per item in a list, a fixed number of times with no list at all, or until a rule you write is met.

DockFlowTakesa list, or a countReturnsa list of results

Where one step does the work per item, the Run for each item setting is simpler and needs nothing on the canvas. Repeater is for a body.

It is a circuit, not a block

This is the one thing worth understanding before you build anything.

Repeater has two outputs. Each time is the body of the loop, and When finished is what happens after it. The steps you connect to Each time run once per pass.

What makes the loop repeat is the connection back: the last step of the body has to connect into the Repeater step again. That returning line is what starts the next pass.

RepeaterEach timeLook upWrite rowback in — this is what starts the next passWhen finished — once, after every passSend summary

Think of it as a circuit rather than a container. The work does not sit inside Repeater; it flows out of Each time, through your steps, and back in.

Check the Execution log after your first test run. Open it from the toolbar and count the steps: Repeater and every step in its body should be there, the body’s steps once per pass.

A run can report that every step succeeded while listing only the steps before the loop. That is the signal the circuit is not carrying: the returning connection is the first thing to check.

Setting it up

Add the step

Open Tools in the dock and choose Repeater under Flow.

Choose how to repeat

How to repeat offers three modes:

  • Once per item in a list: one pass per item. The usual choice.
  • A fixed number of times: a count, with no list involved. Useful for paging through an API or a retry ladder you control yourself.
  • Until a rule is met: passes keep going until what the last one produced satisfies a rule you write. Reach for it when the finish line is a result rather than a count — a paged API that says when it has no more pages, or a job you poll until it reports done.

Point it at the list

For list mode, List takes a reference to a list an earlier step produced, for example {{ 3.result }}. Insert it from the data icon rather than typing it.

Group items into batches, if one call can take several

Items per batch starts at 1, so each pass handles one item. Raise it and each pass receives a group of items instead. Inside the body, {{ item }} then holds the whole group as a list, and the data selector labels it Current batch. The final group can be smaller when the list does not divide evenly.

Group items when one call can handle many records at once, such as an API that accepts fifty rows per request: fewer passes finish a long list sooner.

Build the body

Connect the first step of your loop to the Each time output, then chain as many steps as the work needs.

Close the loop

Connect the last step of the body back into the Repeater step. This is what makes it repeat.

Add what comes after

Anything connected to When finished runs once, after every pass is done.

Referring to the current item

Inside the loop, {{ item }} is the whole item and {{ item.field }} is one of its properties.

Two more give you the position:

ReferenceWhat it holds
{{ item.$index }}Position in the list, counting from 0
{{ item.$total }}How many items there are altogether

Both sit under item. Write {{ item.$index }}, not a bare {{ $index }}.

Steps in the body do not loop on their own

A step inside the body already runs once per pass, so its Each item setting is switched off there. You do not need it: {{ item }} inside the body is the entry this pass is working on.

Why they cannot be combined: both decide how many times a step runs, and each has its own answer. A step set to Each item over 50 records, inside a Repeater running 50 passes, would run 2,500 times. Almost nobody means that, and it is an expensive thing to find out by running it.

For a list inside a list — every order for every customer — use two Repeaters in sequence rather than one inside the other. Flatten the inner list with a Combine step first, then loop over the result.

What decides when the loop stops

In the first two modes the number of passes is settled before the first one runs: it comes from the list’s length, or from the count you typed. Nothing that happens inside the loop changes it.

Until a rule is met works the other way round. Repeater runs a pass, checks your rule against what that pass produced, and either stops or goes round again. The count is decided one pass at a time, which is what lets the loop finish on a result rather than on a number.

Two things follow from that, and both are worth knowing before you build one:

  • The passes run one after another. A pass cannot start before the one before it has been judged, so Passes running at once is held at 1 in this mode whatever it says.
  • The rule may only read the pass that just finished, plus {{ item.$index }} and {{ item.$total }}. Point it at a step outside the loop and the run stops with a message saying the reference is outside the completed pass.

Safety limit is what guarantees the loop ends. In this mode reaching it fails the step rather than finishing quietly, so the run tells you the rule was never met instead of leaving you to wonder whether it was.

Controlling the pace

Passes running at once sets how many passes run concurrently (up to 10, depending on your plan tier; see System Limits).

  • Higher values: Finish long lists sooner.
  • Lower values: Avoid rate limits on external services.
  • Until a rule is met: Stays at 1 because each pass must be evaluated before the next begins.

Most third-party APIs have a rate limit, and a loop is the easiest way to meet it. If you start seeing 429 responses, lower this before changing anything else.

Safety limit caps how many passes the loop may run (default 10,000). Lower this when processing external lists to prevent runaway loops. In Until a rule is met mode, hitting the safety limit deliberately fails the step so you know the condition was never satisfied.

Plan for repeated work. Usage depends on the steps that run in the loop and the work they perform on each pass. See Step Credits, Tokens & Storage. A list whose length you do not control is worth capping: with Safety limit, or with a Filter before it reaches the loop.

When a pass fails

If a pass fails decides what happens next, and it defaults to Stop the run.

SettingWhat happens
Stop the run (default)The loop stops. Passes already done keep what they did: a message sent is still sent. The rest of the list is not attempted.
Skip it and carry onThe remaining passes run. Failures are recorded, and the step finishes successfully.

Which you want depends on the work. Sending a hundred notifications: skip, and chase the failures afterwards. Writing a hundred rows that must all land together: stop, and fix the cause before rerunning.

With skipping on, check {{ N.items }} rather than the step’s status. The step finishes green and {{ N.results }} is simply shorter than the list you put in. If anything downstream depends on every item having been processed, items is where the per-item detail lives.

What it passes on

The loop collects what every pass produced into {{ N.results }}, where N is the step number. That collection is itself a list, so it appears in the next step’s data selector like any other list, and a later step can loop over it in turn.

ReferenceWhat it holds
{{ N.results }}Successful results only, in the order of your input list
{{ N.items }}Every item with its position, status and error
{{ N.stats }}total, succeeded, failed, skipped

stats is what you want for a summary message. “Processed 47 of 50” needs no counting on your side.

results holds successes only, in your input order. When several passes run at once they finish in whatever order the other system answers, and the results are then reordered to match the list you supplied. So {{ 5.results }} is never in completion order.

The consequence worth planning for: when some passes fail, results is shorter than the list you put in. Failures are left out rather than held as empty slots, so position 3 of the results is not necessarily the third item you sent. When you need results lined up against your input, or you need to see what failed, use {{ N.items }}: it carries every item with its position, status and error.

A very large loop fails rather than passing on a partial answer. When the collected results exceed the size Glow carries between steps, the step is marked failed with a message saying so. The work in each pass still happened: the results were too large to hand on. Process the list in smaller pages, or return less per item: an id and a status reach the ceiling far later than whole documents.

Examples to copy

Send one message per person

How to repeat: Once per item in a list. List: {{ 2.ret.records }}.

Connect a Slack Send Message step to Each time, addressed to {{ item.email }} with a body using {{ item.name }}. Connect it back into Repeater. Set Passes running at once to 3 so Slack is not hit all at once.

Enrich a list, then summarise it

List: {{ 1.leads }}. On Each time, an HTTP Request to your enrichment provider, then back into Repeater.

On When finished, an AI Prompt with Summarise these results: {{ 4.stats }}. It runs once, with the totals for the whole loop.

Page through an API

How to repeat: A fixed number of times. Set Number of passes to the number of pages you want.

On Each time, an HTTP Request using {{ item.$index }} as the page number, then back into Repeater. Safety limit stops it if the count is ever miscalculated.

Space out requests to a strict API

Put a Wait of 2 seconds as the last step of the loop body, before the connection back into Repeater. Each pass then waits before the next begins, and the requests arrive spread out rather than all at once.

What’s Next?