Scenarios & executors

A test has one or more scenarios, all running concurrently (offset with start_time). Each scenario picks an executor — the algorithm that schedules iterations. loadr implements all seven k6 executors with identical semantics.

scenarios:
  my_scenario:
    executor: ramping-vus        # which scheduling model
    # ... executor-specific knobs ...
    start_time: 30s              # delay after test start (default 0)
    graceful_stop: 30s           # time for in-flight iterations to finish (default 30s)
    exec: myJsFunction           # JS function to run per iteration (optional)
    flow: [ ... ]                # declarative steps per iteration (optional; needs flow and/or exec)
    pacing: { iterations_per_second: 10 }   # constant-throughput governor
    think_time: { type: constant, duration: 1s }  # default pause after each request
    tags: { kind: api }          # tags on all samples from this scenario

Closed-model executors

New iterations start only when a VU finishes its previous one — throughput depends on response times (a coordinated-omission-prone model; use open models to control offered load).

constant-vus

executor: constant-vus
vus: 50
duration: 5m

ramping-vus

VU count follows linear ramps between stage targets.

executor: ramping-vus
start_vus: 0
stages:
  - { duration: 2m, target: 100 }   # ramp 0 → 100
  - { duration: 5m, target: 100 }   # hold
  - { duration: 1m, target: 0 }     # ramp down
graceful_ramp_down: 30s             # grace for iterations on de-allocated VUs

per-vu-iterations

Each VU runs exactly N iterations.

executor: per-vu-iterations
vus: 10
iterations: 100        # per VU → 1000 total
max_duration: 10m      # safety cap (default 10m)

shared-iterations

A pool of N iterations split dynamically among VUs (fast VUs do more).

executor: shared-iterations
vus: 10
iterations: 1000       # total
max_duration: 10m

Open-model executors

Iterations start on schedule regardless of completion — the offered load is what you configured, and saturation shows up as dropped_iterations instead of silently lower request rates.

constant-arrival-rate

executor: constant-arrival-rate
rate: 100              # iteration starts per time_unit
time_unit: 1s          # default 1s (rate: 6000 + time_unit: 1m ≡ 100/s)
duration: 10m
pre_allocated_vus: 50  # workers created up front
max_vus: 200           # pool may grow to this before dropping iterations

ramping-arrival-rate

executor: ramping-arrival-rate
start_rate: 10
time_unit: 1s
pre_allocated_vus: 50
max_vus: 500
stages:
  - { duration: 2m, target: 100 }   # linear rate ramp
  - { duration: 5m, target: 100 }

externally-controlled

VU count is set at runtime — from the web UI's run page, the controller API, or programmatically. Great for exploratory "turn the dial" testing.

executor: externally-controlled
max_vus: 500
duration: 30m          # optional; omit to run until stopped

Graceful stop semantics

When a scenario's schedule ends (or the run is stopped), no new iterations start; in-flight iterations get graceful_stop (default 30s) to finish before being cancelled. ramping-vus additionally applies graceful_ramp_down to VUs being de-allocated mid-iteration during a downward ramp.