# System Limits & Quotas

> The ceilings that apply to workflow execution in Glow: batch sizes, concurrency, retries, timeouts, and payload limits, by plan.

The ceilings that apply when a workflow runs: batch sizes, step timeouts, webhook payloads, and how long a run stays in your history. Limits that depend on your plan say so.

## Every limit, in one table

The figures you are most likely to be looking for. Each has its own section below with what to do when you reach it.

| Limit                              | Figure                                | Depends on plan |
| ---------------------------------- | ------------------------------------- | --------------- |
| **Items in one looping step**      | 50 / 1,000 / 10,000                   | Yes             |
| **Items processing at once**       | 1 / 5 / 10                            | Yes             |
| **Items a Filter can check**       | 100,000                               | No              |
| **In-field list transformation**   | 10,000 items                          | No              |
| **Repeater Until-condition limit** | 50 passes (default safety cap)        | No              |
| **Webhook payload**                | 1 MB per request                      | No              |
| **App trigger payload**            | 10 MB per request                     | No              |
| **Outbound HTTP response payload** | 10 MB per request                     | No              |
| **Combined results of a loop**     | 25 MB                                 | No              |
| **Single file upload**             | 100 MB                                | No              |
| **AI Agent run**                   | 150 seconds                           | No              |
| **Code editor run**                | 150 seconds                           | No              |
| **Outbound HTTP request timeout**  | 30 seconds by default, 300 at most    | No              |
| **Wait**                           | 13 days                               | No              |
| **Human Review expiry**            | 30 days                               | No              |
| **Retries on a failed step**       | 0–10, off unless you turn them on     | No              |
| **Run history**                    | See [Data Retention](#data-retention) | Yes             |

Everything here is enforced when a workflow runs, not when you build it. A
workflow that works on forty test records can fail at sixty.

## Batch processing (Run for each item)

When a step runs in [Run for each item](/build/action-steps/loops/run-for-each-item) mode, four limits apply. Three of them depend on your plan; the fourth is your credit balance.

| Limit                  | Free | Pro   | Enterprise |
| ---------------------- | ---- | ----- | ---------- |
| **Items per batch**    | 50   | 1,000 | 10,000     |
| **Parallel item runs** | 1    | 5     | 10         |
| **Retry failed items** | No   | Yes   | Yes        |

**Items per batch** is the ceiling on the list (array) you feed into the step. A list longer than the limit is rejected when the step fans out.

The [Repeater](/build/action-steps/loops/repeater) step has a field of the same name, and it means something else: how many items one pass receives. These plan limits are about the length of the whole list.

**Parallel item runs** is how many items process simultaneously. Free plans process strictly one at a time.

**Retry failed items** lets a batch continue past individual failures and retry them. Available on Pro and Enterprise.

**Account for repeated work.** Usage depends on the step's rate and the work it performs for each item. See [Step Credits, Tokens & Storage](/manage/billing/credits-and-allowances) for how usage is counted, including failed attempts. A list whose length you do not control is worth capping with a [Filter](/build/action-steps/filter-items) before it reaches the looping step.

**Not every step can loop.** The toggle is absent on flow control: Conditions, Switch, Filter. It is also absent on steps that wait (Wait, Human Review), and on steps with no per-item work to do (Stop and Error, Do Nothing). Triggers never loop, because they start the run.

**Need a pause between passes?** Put a [Wait](/build/action-steps/delay) as the last step of a [Repeater](/build/action-steps/loops/repeater) loop body, before the connection back into the Repeater step, rather than trying to loop the Wait itself.

## Filter

A [Filter](/build/action-steps/filter-items) step evaluates up to **100,000 items** in a single pass. That ceiling is separate from the batch limits above. Filtering is not the same mechanism as "Run for each item".

The same 100,000-item ceiling applies to [Sort](/build/action-steps/sort), [Limit](/build/action-steps/limit) and [Remove duplicates](/build/action-steps/remove-duplicates). Each refuses a longer list with a message naming both numbers, rather than returning a partial answer. [Sort](/build/action-steps/sort) also takes at most **ten** "Sort by" rows.

## Retries

Two separate mechanisms retry work, and they are easy to confuse.

### Retry on fail (yours to configure)

A per-step setting in the step's **Test & Debug** tab. This is the one that produces the **Attempt 2 of 11** markers in the step's execution history. The second number is your retry budget plus the first run.

| Setting                | Range        | Default |
| ---------------------- | ------------ | ------- |
| **Retry on fail**      | on / off     | **Off** |
| **Max retries**        | 0–10         | 10      |
| **Wait between tries** | 0–60 seconds | 60      |

**The count is retries, not attempts:** 10 means the step runs eleven times before the run fails. The form opens at the ceiling of both settings: ten retries, sixty seconds apart. That is roughly ten minutes of a run held open on one step. Lower both before you turn retries on, unless you mean it.

The wait is a **fixed** interval, not exponential. Retries are off unless you turn them on, so a step that fails once fails the run unless you have configured otherwise. See [Error Handling](/build/core-concepts/error-handling).

> **Retries do not inspect why the step failed.** A request the other service
> rejected outright (a `400` from a malformed payload, a `404` on a record that
> is not there) is re-sent unchanged on every attempt. It fails identically
> every time. At the defaults that is ten attempts a minute apart: ten minutes
> of a run held open for a result that cannot change.
>
> Three things are exempt: an expired connection, [Stop and Error](/build/action-steps/stop-and-error), and a step whose outward call may already have landed. See [Three things never retry](/build/core-concepts/error-handling#three-things-never-retry). Turn retries on for what is genuinely transient. Rate limits, timeouts, or a service having a bad minute. For a step that fails on its own input, fix the input instead, or route it through an [error path](/build/core-concepts/error-handling).

**Inside [Run for each item](/build/action-steps/loops/run-for-each-item) it works differently.** A failed item is retried only when the failure looks retryable: a `429`, a `5xx`, a dropped connection. A rejection like `400` moves straight to failed without burning the budget.

### Make repeatable steps safe to run twice

Separately from your own retry setting, a step can occasionally run a second time — if the worker handling it is interrupted part-way through, for instance. It is rare, and it carries no attempt marker in the execution history.

So a step that charges a card, sends a message or creates a record is worth making safe to run twice: send an idempotency key where the service accepts one, or check for the record before creating it. That holds on any platform, and it is the one habit that makes a workflow safe to retry at all.

Deliberate waits are **not** counted by either mechanism. A [Wait](/build/action-steps/delay) step, or a scheduled backoff after a third-party rate limit, is re-queued rather than retried. It consumes no retry budget and shows no attempt marker.

## Timeouts

| Scope                 | Limit                                               |
| --------------------- | --------------------------------------------------- |
| AI Agent run          | 150 seconds                                         |
| Code editor run       | 150 seconds                                         |
| Code editor memory    | 1.5 GB                                              |
| Outbound HTTP request | 30 seconds default, 300 max                         |
| Code editor output    | 100,000 characters                                  |
| Wait step             | 13 days (a larger number is refused as you type it) |
| Human Review expiry   | 30 days (a larger number is refused as you type it) |

An [HTTP Request](/build/action-steps/http-request) uses a 30-second timeout by default. Raise it when the remote service needs longer, up to the 300-second maximum. For work that cannot finish within one request, have the service accept the job and call a [Webhook](/build/triggers/webhook) when it finishes.

A [Wait](/build/action-steps/delay) step takes an **Amount** and a **Unit**, from seconds up to days. It re-queues the run rather than holding a worker, so long waits are cheap. It accepts up to **13 days** and refuses a larger value as you enter it. If you need a wait measured in weeks, a [Scheduler](/build/triggers/scheduler) trigger on a second workflow is the sturdier shape.

A [Human Review](/build/action-steps/user-approval) step with no expiry holds the run until someone decides. Set an expiry, capped at **30 days**, and mark one of your Decisions rows as the **Expired** branch: a request nobody answers then takes that branch, so you can chase it, escalate it, or carry on without it. With no row marked, the timeout settles the run through the step's error path.

A [Code editor](/build/action-steps/code-execution) step keeps at most 100,000 characters of output; past that the result is stored truncated. If you are processing large datasets, filter before the expensive work or return a summary rather than the whole thing.

An exported workflow file is accepted up to **512,000 characters**. A larger export from another platform has to be split before it will import — see [Migrating to Glow](/getting-started/migrating-to-glow).

## Payloads and storage

| Scope                                | Limit                                        |
| ------------------------------------ | -------------------------------------------- |
| Payload to a Glow webhook trigger    | 1 MB per request                             |
| Payload to an app's built-in trigger | 10 MB per request                            |
| Combined results of a loop           | 25 MB                                        |
| Single file upload                   | 100 MB, on every plan                        |
| Team file storage                    | Per plan; see the storage meter in **Files** |

A request over the payload ceiling is refused before a run starts, so there is nothing in your history to look at afterwards. If a partner system sends large bodies, have it send you a reference instead, such as an id or a link. Fetch the rest with an [HTTP Request](/build/action-steps/http-request) step.

**The 25 MB loop ceiling applies to everything the items returned together**, not to any one item. A [Run for each item](/build/action-steps/loops/run-for-each-item) step that exceeds it fails and does not pass its results on. Process the list in smaller pages, or return less per item. A step that fetches whole documents will reach the ceiling long before one that returns an id and a status.

The storage meter on the [File Management](/manage/workspace-settings/file-management) page shows current usage against your team's quota. A single file over 100 MB is rejected rather than truncated; leave anything larger in the service that owns it and fetch it at run time with an [HTTP Request](/build/action-steps/http-request).

## Data retention

| Data                                             | Default workspace policy       |
| ------------------------------------------------ | ------------------------------ |
| Run records and step-level input/output payloads | 30 days after the run finishes |

**Each run keeps the retention policy in effect when it started.** A policy
change applies to new runs only; it does not shorten or extend what is already
in your history.

> **Glow is not a system of record.** The default 30-day policy covers debugging
> and a monthly review. If you need a lasting audit trail, send what matters out
> as it happens: an [HTTP Request](/build/action-steps/http-request) step to
> your own logging, or a message to the channel your team watches. Your
> workspace may use a different retention policy; your account team can confirm
> its current setting.

See [Step-level Executions](/build/core-concepts/executions) and
[Security & Compliance](/manage/workspace-settings/security-compliance).

## MSP impersonation sessions

Available session durations: 5m, 15m, 30m, 1h, 3h, 6h, 12h, 24h, 3d, 7d, 14d, 30d, with a hard 30-day ceiling.

Sessions are re-validated continuously, not only at expiry. If a client withdraws consent or downgrades the access tier mid-session, the operator's next request is refused and any open canvas disconnects within 30 seconds. See [Governance & Impersonation](/msp/governance).

## Raising a limit

Batch size, concurrency, and item retries are tied to your subscription. See [Billing & Usage](/manage/billing/overview) to compare tiers.

For Enterprise requirements beyond the values above, contact your account team.

## What's Next?

- Design around failures with [Error Handling](/build/core-concepts/error-handling).
- Diagnose a specific failure in [Troubleshooting](/reference/troubleshooting).
