# Run states and limits

Each state’s word in the dashboard and in the API, and the limits a run works within.

## States

Each run has a `status` in the API. A list of runs also gives each its `state`, in the dashboard’s words. For what each state means, see [Runs](https://docs.gorunner.io/build/runs#states).

| Dashboard | `state` (List runs) | `status` |
| --- | --- | --- |
| Queued | `queued` | `waiting` |
| Running | `running` | `pending`, `running`, or `paused` in a Delay |
| Held | `held` | `paused` with `waitingOn: person` |
| Worked | `worked` | `completed` |
| Failed | `failed` | `failed` |
| Cancelled | `cancelled` | `cancelled` |

`completed`, `failed` and `cancelled` are final: stop polling there. A rejected approval is still **Worked**; its `decision` says `rejected`.

**What is the difference between pending and running?**

`pending`: a worker has the run or is about to take it. `claimedAt` says when one took it. `running`: a run carrying on after a wait.

**How do I see why a run is Queued?**

A `waiting` run has `waitingFor`: `workflow` or `organization`, the limit that holds it, with `waitingLimit`. `linePosition` is its place, 1 being next. With no `waitingFor`, it is waiting for a free worker, usually for a moment.

## Test and production

| What | Test | Production |
| --- | --- | --- |
| Started by | **Test** in the editor, or **Listen for the next real event** while the workflow isn’t Live | The trigger of a Live workflow, **Run**, or the API |
| Runs | The draft | The published version |
| Pinned step data | Used | Ignored: every step runs |
| In Runs | Only with **Include test runs** | Always |
| `environment` | `test` | `production` |

## Times

- `startedAt`: When the run was accepted.
- `firstStartedAt`: When a worker first started it. The gap from `startedAt` is the time it waited in line.
- `durationMs`: From `firstStartedAt` to the end, rounded to the millisecond. Waits inside the run, such as a Delay, count.
- `finishedAt`: When its result was decided. Both are there as soon as the run ends.

On a run’s page, hover over or focus the time in the top bar to see where it went, such as **Took 697 ms · steps 456 ms · start-up 241 ms · waited in line 2.1 s (not counted)**. A time under half a millisecond shows **\<1 ms**.

A run started on v2026.10.5 or earlier, or one that ran inline, such as a Sub-flow’s, counts from `startedAt`.

## Limits

- **A step’s **Timeout****: 30 seconds, unless you set another or the app needs longer, up to 600. Each retry gets it again.
- **Retry on failure**: Up to 5 retries.
- **The workflow’s **Execution timeout****: 5 minutes when 0, up to 1 hour. Delays and approvals don’t count.
- **A Code step**: 30 seconds and 256 MB of memory.
- **An expression**: 100 ms.
- **What one step passes on**: 16 MB.
- **A webhook’s body**: 5 MiB.
- **A caller that waits for the answer**: Up to 30 seconds, in line and running together. Then it gets `202` with the run’s id, and the run carries on. When the server already holds as many waiting callers as it can, it gets that `202` at once.
- **Runs at once**: None, unless the workflow sets a limit, or one is set for your organization (by a platform admin, or by your provider in the Embed).
- **Runs waiting in line**: 10,000 for an organization, 1,000 for one workflow. Then new runs get `429 RUNS_WAITING_LIMIT`.

**Self-hosted:** `MAX_STEP_OUTPUT_BYTES`, `SCRIPT_MEMORY_LIMIT_MB`, `RUNS_WAITING_PER_ORG` and `RUNS_WAITING_PER_WORKFLOW` change these, and `RUN_RETENTION_DAYS` changes [how long runs are kept](https://docs.gorunner.io/build/runs#how-long-runs-are-kept). See [Settings (.env)](https://docs.gorunner.io/self-host/settings).

**Does a held run take a place?**

It keeps its workflow’s place, but frees its organization’s, so an approval left for days doesn’t hold up other workflows.

**Which runs never wait in line?**

Runs started by an **Error** or **Run Finished** trigger, and a Sub-flow’s run, start at once. A schedule skips its turn while a run of it still waits.

## If a worker stops mid-run

An accepted run is never dropped. A worker stopped normally, as in an update, finishes its runs first. One that stops without warning, when it is killed or runs out of memory, is noticed within about 10 seconds, or about 3 minutes when its whole server is gone. Another worker then carries on from what was finished:

- **A finished step**: Doesn’t run again. Its result is used.
- **A running step that reads or computes**: Runs again.
- **A running step that changes something outside**: Such as an email, a `POST` or a new row. It isn’t sent again: it fails with **Outcome unknown**, and its error handling decides what happens next. Check the service it calls.

If the record of what was finished is lost, because Redis lost its data, a run that could change something outside fails with **Progress unknown** instead of starting over. One that only reads starts again from its first step. Runs in progress carry on through a Redis outage of up to about 2 minutes.

The run’s page says **Restarted once** or **Restarted 2 times**, and each step’s record says whether it was kept, ran again, or its outcome is unknown. In the API, the run has `restarts`, and each step `recovery` (`replayed`, `rerun` or `unknown`) and `runAttempt`. After the third stop the run fails with **This run’s worker stopped 3 times, so the run was stopped.**

## Related

- [Runs](https://docs.gorunner.io/build/runs): What a run is, and the Runs list · 4 min
- [Limit runs at once](https://docs.gorunner.io/build/runs-at-once): Wait in line, or refuse · 4 min
- [Get a run](https://docs.gorunner.io/api/runs/get-run): Read a run’s status from the API

Source: https://docs.gorunner.io/build/run-states
