---
title: Split in Batches
description: Loop over a list a batch at a time, running the body once per batch
---

Work through a list a few items at a time, running the same steps once per batch.

## What it does

Split in Batches works like [Loop](/nodes/builtin/flow/loop/), but instead of a condition you give it a list. It has two inputs and two outputs:

* **Input** (top): where the data first comes in.
* **Loop Back** (bottom input): connect the last step of the repeated part here.
* **Loop** (output): gets the next batch; the steps to repeat start here.
* **Done** (output): runs once, after the last batch.

On each pass it sends the next **Batch size** items out of **Loop** and waits for them to come back through **Loop Back** before sending the next ones. With 7 items and a batch size of 3, the steps run three times, with items 1-3, 4-6 and 7, then the workflow continues from **Done**.

* An empty list goes straight to **Done**. A single value that is not a list counts as one batch of one item.
* As a safety limit, the node stops after 1,000 passes, even if items are left.
* If the run pauses in the middle (for example on a [Wait For Approval](/nodes/builtin/flow/wait-for-approval/) inside the loop), it resumes at the right batch.

## When to use it

* Send rows to an API 10 at a time because it rejects large requests.
* Ask for an approval or show a form once per item (batch size 1).
* Slow down: add a [Wait](/nodes/builtin/flow/wait/) inside the loop so a site or API isn't hit too fast.

Most nodes already run once per item, so you don't need Split in Batches just to handle every item of a list. To repeat until a condition changes, use [Loop](/nodes/builtin/flow/loop/).

## Inputs and settings

Set **Items** to an expression that returns a list, for example `{{ $input.data.contacts }}` after an Http Request. If your data arrives as many separate items, gather them into one list first with [Aggregate](/nodes/builtin/datatransformation/aggregate/).

## Outputs

Each output item has these fields:

```json title="Shape of an output item"
{
  "done": true,
  "batch": [],
  "batchIndex": 0,
  "isLast": true,
  "items": []
}
```

In the repeated steps, read the current batch with `{{ $input.batch }}`. `batchIndex` counts batches from 0, and `isLast` is true on the final batch. From **Done**, `{{ $input.items }}` still gives you the whole list.

## Dependencies and credentials

None. This node needs no connection and has no slots for other nodes.

## Example workflow

Send contacts to an API 25 at a time:

1. [Http Request](/nodes/builtin/core/http-request/) gets `https://api.example.com/contacts`, which returns `{ "contacts": [...] }`.
2. Split in Batches with **Items** `{{ $input.data.contacts }}` and **Batch size** `25`.
3. From **Loop**: a second Http Request, **POST** to `https://api.example.com/contacts/bulk` with `{{ $input.batch }}` in the JSON body, then [Wait](/nodes/builtin/flow/wait/) with **Amount** `2` and **Unit** **Seconds**. Connect the Wait to **Loop Back**.
4. From **Done**: [Show Notification](/nodes/extension/shownotification/) says `All contacts sent`.

## Common issues

* **The steps run only once.** The last repeated step is not connected to **Loop Back**, so the node never gets asked for the next batch. Connect it to the bottom input, not the top one.
* **It goes straight to Done.** **Items** resolved to an empty list or to nothing. Check the expression in the run's input for this node; it must point to a list.
* **Nothing runs after the loop.** Connect the next steps to **Done**, not to **Loop**.
* **It stopped before the end of a very long list.** The node stops after 1,000 passes. Raise **Batch size** so the list fits in fewer passes.

## Related nodes

* [Loop](/nodes/builtin/flow/loop/): repeat while a condition holds.
* [Split Out](/nodes/builtin/datatransformation/splitout/): turn a list field into separate items, without looping.
* [Wait](/nodes/builtin/flow/wait/): pause between batches.
* [Aggregate](/nodes/builtin/datatransformation/aggregate/): gather items back into one list.