# Repeater

> The step that repeats a body of several steps: once per item in a list, a fixed number of times, or until a rule is met.

**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.

> Dock: Flow · Takes: a list, or a count · Returns: a list of results

Where one step does the work per item, the [Run for each item](/build/action-steps/loops/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.

Two loop shapes: Run for each item fans one step out over a list, while the Repeater sends the flow back around a circuit. See /build/action-steps/loops.

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:

| Reference           | What 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](/build/action-steps/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](/reference/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](/manage/billing/credits-and-allowances). A list whose length you do
> not control is worth capping: with **Safety limit**, or with a
> [Filter](/build/action-steps/filter-items) before it reaches the loop.

## When a pass fails

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

| Setting                    | What 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 on**   | The 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.

| Reference         | What 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](/build/action-steps/delay) 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?

- [Run for each item](/build/action-steps/loops/run-for-each-item) — the simpler setting, when one step does the work.
- [System Limits](/reference/system-limits) — concurrency and per-item retries by plan.
- [Variable Syntax](/reference/variable-syntax) — the full reference for `{{ }}`.
