# Custom Variables

> Hold a value under a name you choose, and read it back anywhere later in the same run.

The **Custom Variables** step holds one or more values under names you choose, so later steps can read them back by name.

> Dock: Data · Change · Takes: any value · Returns: each variable by name

**Keyboard shortcut:** `t+v`

## When it is worth one

Any step can already read any earlier step by number, so a variable is not how you move data forward. `{{ 3.email }}` does that on its own.

Reach for one when the value is not already sitting in an earlier step's output. A running total you keep adding to, a flag you set once and check much later, or a starting value you want written down in one obvious place instead of repeated across four fields.

## Setting it up

1. Press `t+v`, or open **Tools → Data → Change** in the dock and select **Custom Variables**.
2. Under **Variables**, type a name in the **Name** column and its value in the **Value** column. Each variable takes one row, and the step opens with an empty row ready to fill.
3. Select **Add variable** for each further value. One step can define several variables at once, which keeps the canvas shorter than a step per value. The minus at the end of a row removes that variable.
4. The value can be typed in directly (`0`, `pending`), or picked from an earlier step. The picker sits on the value only: a name is always something you type.

> **A variable lasts one run and no longer.** The next run starts with nothing
> set, whatever the last one left behind. To keep a value between runs, put it
> in a [workspace variable](/manage/workspace-settings/secrets-and-variables), a
> spreadsheet row, or a record in your own system.

> **Each Custom Variables step keeps its own values.** Two steps can both set a
> `status`, and they do not overwrite each other: `{{ 3.status }}` and
> `{{ 7.status }}` are two different values, read from two different steps.
> Within one step, a name used on two rows keeps the later row's value.

## Types

Each row carries a **type**, shown beside its value: **Text**, **Number**,
**Yes/no**, **List** or **Record**. It is set for you as you type — write
`["red", "amber", "green"]` and the row reads **List**; write `42` and it reads
**Number**.

```
["red", "amber", "green"]  row reads List
{"plan": "pro"}            row reads Record
42                         row reads Number
true                       row reads Yes/no
```

A typed list is a real list downstream: point **Run for each item** at it and it
runs once per entry, the same as a list from an earlier step.

**A row holding a reference is Text.** `{{ 3.ret.items }}` on its own still
arrives as whatever that step produced, with its type intact — the row shows Text
because the value is a reference until the run resolves it, not because the list
is flattened.

Mix a reference into surrounding text and the result really is text.
`Order {{ 3.id }} for {{ 3.customer }}` is one sentence, and that is all
combining values this way can produce.

## What it passes on

Each variable becomes a field on the step, named exactly as you named it. A step 3 that sets `discount_rate` is read downstream as:

```
{{ 3.discount_rate }}
```

There is no wrapper in between. The variable name follows the step number directly. Insert references from the data picker rather than typing them, and check the [Variable Reference Syntax](/reference/variable-syntax) if a path is not resolving.

## Examples to copy

### A decision made early, used late

A workflow looks up a customer at step 2. It needs their loyalty tier at step 9, after a lookup, a branch and a loop have all run.

1. At step 3, set `loyalty_tier` from the CRM lookup.
2. At step 9, use `{{ 3.loyalty_tier }}` to pick the discount.

You could reference the CRM step directly. The variable earns its place when the tier comes from somewhere different depending on the branch taken. Then one name means one thing, wherever the run went to find it.

### A flag decided mid-flow

1. Somewhere in the middle, a Custom Variables step (say step 7) sets `requires_approval` from a rule: an amount over the threshold makes it `true`.
2. At the end, branch on `{{ 7.requires_approval }}` to decide whether to route through [Human Review](/build/action-steps/user-approval).

**Read the flag from the step that set it.** A variable belongs to its step, so a later step setting the same name does not change an earlier one. The branch has to reference the step whose value it wants.

### Counting what a loop did

You do not need a variable for this. A step running per item passes on `{{ N.stats }}`, with `total`, `succeeded`, `failed` and `skipped` already counted. See [Loops & Iteration](/build/action-steps/loops). Reach for a variable only when you are counting something the loop does not track for you.

## What's Next?

- Reference stored values correctly using the [Variable Reference Syntax](/reference/variable-syntax).
- Store values that must persist across runs in [Secrets and Variables](/manage/workspace-settings/secrets-and-variables).
