For the complete documentation index, see llms.txt. This page is also available as Markdown.

Execution controls

Use a looping strategy to run a stage or step multiple times; iterate a fixed number of times with a for loop, loop conditionally with a while loop, or fan out across input combinations with a matrix.

A strategy tells Harness to run a stage or step more than once. Instead of duplicating stages or steps for each environment, region, or input combination, you define the variation once and let the strategy expand it at runtime.

Strategy can be applied at the stage level (each instance runs as a separate stage) or the step level (each instance runs as a separate step within the same stage).

What you will learn

  • How to use for loop, while loop, and matrix strategies to run a stage or step multiple times

  • How matrix fans out across combinations of values and how to reference axis values in steps

  • How to exclude specific matrix combinations and customize instance names with node-name

  • How max-parallel and fail-fast control strategy execution behavior

The Strategy panel has three shared settings that apply to all strategy types:

Field
Description

Max parallel

Maximum number of strategy instances that run simultaneously. Set to 0 for unlimited (default).

Fail fast

When true, cancels all running instances if any one instance fails.

Strategy type

The looping type: For loop, While loop, or Matrix.


For loop

A for loop runs the stage a fixed number of times. Each iteration runs as a separate stage instance. By default, all instances run in parallel.

stages:
  - name: build
    id: build
    strategy:
      max-parallel: 0
      fail-fast: true
      for:
        iterations: 3
    steps:
      - name: run
        id: run
        run:
          script: |
            echo "Iteration: ${{ strategy.iteration }}"
            echo "Total: ${{ strategy.iterations }}"

Verified expression output for 2 iterations:

Expression
Resolves to

${{ strategy.iteration }}

Current iteration index (0-based): 0, 1

${{ strategy.iterations }}

Total number of iterations: 2

Stage naming: each instance is named <stage_id>_<index>. A stage with id: build and iterations: 3 produces build_0, build_1, build_2.

for only accepts integer iterations. A list of string items is not supported.


While loop

A while loop runs the stage up to a maximum number of iterations. Each iteration runs sequentially; the next instance starts only after the previous one finishes.

Stage naming follows the same pattern as for loop: poll_0, poll_1, poll_2.

Unlike the for loop, while loop instances always run one at a time regardless of max-parallel.


Matrix

A matrix runs the stage once for every combination of values across one or more axes. All combinations run in parallel by default. The total number of instances is the product of all axis lengths minus any excluded combinations.

Basic example

This produces four instances (all 2×2 combinations):

Instance

${{ matrix.os }}

${{ matrix.node }}

test_0_0

linux

18

test_0_1

linux

20

test_1_0

windows

18

test_1_1

windows

20

Stage naming uses axis index pairs: <stage_id>_<axis1_index>_<axis2_index>.


Browser and OS testing

Run a test suite across every browser/OS combination with a concurrency cap to avoid overloading infrastructure:

Produces 9 combinations. Reference values in steps with ${{ matrix.browser }} and ${{ matrix.os }}.


JDK version matrix (single axis)

A single-axis matrix is the simplest form: run the same stage once for each value in a list. With max-parallel set, instances beyond the cap queue until a slot opens:

Reference the current JDK version with ${{ matrix.jdk }}. Single-axis instances are named <stage_id>_0, <stage_id>_1, <stage_id>_2 (not _0_0 like multi-axis).


Service × environment deployment

Deploy multiple services to multiple environments, with a specific combination excluded:

This produces 5 instances (3×2 = 6, minus 1 excluded). Reference with ${{ matrix.service }} and ${{ matrix.environment }}.


Exclude combinations

Exclude a specific pair:

Exclude all combinations containing a value (omit one key to match any pairing):

This removes all three macos combinations, producing 6 instances instead of 9.


Custom instance names with node-name

By default, instances are named <stage_id>_0_0, <stage_id>_0_1, etc. Use node-name to give instances meaningful names:

This produces stage identifiers: deploy_api_staging, deploy_worker_staging, deploy_api_production, deploy_worker_production.

Hyphens in the resolved node-name are converted to underscores in the stage identifier. The original stage id is prepended: <stage_id>_<node-name>.

Avoid hyphens in axis names (e.g. use nodeVersion not node-version). Hyphens in axis names cause expressions like ${{ matrix.node-version }} to resolve as null.


Comparison

For loop
While loop
Matrix

Input

Integer count

Integer count

One or more value lists

Default execution

Parallel

Sequential

Parallel

Stage naming

<id>_0, <id>_1

<id>_0, <id>_1

<id>_0_0, <id>_0_1

Current value expression

${{ strategy.iteration }}

${{ strategy.iteration }}

${{ matrix.<axis> }}


Next steps

Last updated

Was this helpful?