Which k6 scenario do the root vus and iterations options build, and what does duration do there?
answer
- the shortcut has a target executor
- total across VUs, not per VU
- duration lands on a different key
- derived scenario is named default
- shared-iterations is what you get
basics
~20 sk6 turns root vus and iterations into a single scenario named default that uses the shared-iterations executor, so iterations is the total across all VUs. A root duration set alongside them becomes that scenario's maxDuration.
solid answer
~40 sSetting `vus` and `iterations` at the **root** of k6's exported `options` is a shortcut: k6 derives one scenario called `default` running the **`shared-iterations`** executor. So `iterations` is the total across all VUs, not a per-VU count — the `-i` flag's help even says *script total iteration limit (among all VUs)*. If you also set a root `duration`, it is not a competing run length; k6 copies it into the derived scenario's `maxDuration`, replacing the `'10m'` default. Combining root `iterations` with `stages` or with an explicit `scenarios` map is rejected outright rather than merged. With no execution options at all, k6 falls back to a `per-vu-iterations` scenario of one VU and one iteration.
code
javascript · 18 lines// Shortcut form: 500 CSV rows, 20 VUs, 30 minute ceiling.
export const options = {
vus: 20,
iterations: 500,
duration: '30m',
};
// Exactly what k6 derives from it:
export const equivalent = {
scenarios: {
default: {
executor: 'shared-iterations',
vus: 20,
iterations: 500,
maxDuration: '30m',
},
},
};go deeper
Know the mapping cold: root vus plus iterations equals one shared-iterations scenario called default, and iterations is the total across all VUs. That single fact answers most screening questions on k6 options.
Be able to write out the longhand scenario the shortcut expands to, and explain that a root duration lands on maxDuration rather than replacing the budget. Know that the no-options fallback is per-vu-iterations instead.
Say when you stop using the shortcut: more than one scenario, a startTime, a per-scenario exec, or per-VU semantics. Note that adding a scenarios map is an error while root iterations is still set, so it is a move not an addition.
Treat the shortcut as fine for a throwaway or a smoke run and a liability in a shared suite, where the derived executor is invisible in review. Standardising on explicit scenarios makes the executor a reviewable choice.
## The shortcut and what it derives k6 lets you skip the `scenarios` map entirely for simple runs. Setting the **root** options `vus` and `iterations` — at the top level of the exported `options` object, not inside a scenario — makes k6 build a single scenario for you. That scenario is named `default` and it uses the **`shared-iterations`** executor, so `iterations` is the **total** across all VUs, not a per-VU figure. The `--iterations`/`-i` flag says as much in its own help text: *script total iteration limit (among all VUs)*. ```javascript export const options = { vus: 5, iterations: 10 }; ``` is the same run as: ```javascript export const options = { scenarios: { default: { executor: 'shared-iterations', vus: 5, iterations: 10 }, }, }; ``` ## What `duration` does when `iterations` is also set This is the part people get wrong. A root `duration` alongside a root `iterations` does **not** turn the run into a timed one and does not fight with the budget — it is copied into the derived scenario's `maxDuration`, replacing the `'10m'` default. So `k6 run -u 1 -i 6 -d 10s script.js` is a six-iteration `shared-iterations` run with a ten-second ceiling. ## The full derivation order k6 checks the root options in a fixed order and the first match wins: 1. `iterations` set → a `shared-iterations` scenario, taking `vus` and using `duration` as `maxDuration`. 2. otherwise `duration` set → a `constant-vus` scenario. 3. otherwise `stages` set → a `ramping-vus` scenario. 4. otherwise `vus` set alone → a `shared-iterations` scenario where **`iterations` is set equal to `vus`**, so `k6 run --vus 8 script.js` runs 8 iterations across 8 VUs and exits. 5. otherwise `scenarios` set → used as written, nothing is derived. 6. otherwise nothing at all → a `per-vu-iterations` scenario with 1 VU and 1 iteration. That is why a bare `k6 run script.js` executes the default function exactly once. Note the asymmetry between branch 4 and branch 6: the *zero-options* default is `per-vu-iterations`, while every iteration **shortcut** lands on `shared-iterations`. Because the branches are ordered rather than combined, `iterations` also beats a `duration` you set for a different reason — there is no way to express "run for ten minutes *and* stop at 500 iterations" as two independent limits through the shortcut, since the second one is reinterpreted as the ceiling of the first. ## Conflicts k6 refuses - `iterations` together with `stages` is rejected: *using `iterations` and `stages` options simultaneously is not allowed*. - `iterations` together with `scenarios` is rejected the same way. The shortcut and the explicit map are mutually exclusive, not merged, so there is no partial-override behaviour to reason about. - The message names the two options directly, which is usually enough to locate the problem: the pair may have arrived from two different places, for instance `iterations` from an environment variable and `scenarios` from the script. - The bare-`vus` branch behaves differently: with a script-defined `scenarios` map it does **not** fail, it logs a warning that `vus=N` overrides the scenarios configuration and the derived shortcut wins. ## Where you can set it The same shortcut is available in all three places k6 reads configuration from, with the same meaning: | form | example | |---|---| | exported `options` | `export const options = { vus: 5, iterations: 10 };` | | environment | `K6_VUS=5 K6_ITERATIONS=10 k6 run script.js` | | CLI flags | `k6 run -u 5 -i 10 script.js` | k6's own `k6 run` help lists `# Run 5 VUs, splitting 10 iterations between them.` next to `-u 5 -i 10` — "splitting" being the giveaway that this is the shared, not the per-VU, executor. ## When to stop using it: the 500-row CSV pass For a 500-row data-driven pass the shortcut is genuinely enough: `export const options = { vus: 20, iterations: 500 };` runs each row once. Write the scenario out longhand as soon as you need something the shortcut cannot express: - a `maxDuration` that is not simply the root `duration`, or a `startTime`; - `per-vu-iterations` semantics, which no root shortcut can produce; - more than one scenario, or a named scenario other than `default`; - a scenario-level `exec` pointing at a function other than the default export; - scenario-level `env` or `tags` that should apply to this workload and not the whole run. Because reaching for `scenarios` and keeping the root `iterations` is an error rather than a merge, that migration is an edit, not an addition: move `vus` and `iterations` into the scenario entry and delete them from the root.
- What does k6 run script.js do when the script sets no execution options at all?It derives a single scenario named `default` using the `per-vu-iterations` executor with `vus: 1` and `iterations: 1`, so the default function runs exactly once. Note the asymmetry: the no-options fallback is `per-vu-iterations`, while every iteration shortcut lands on `shared-iterations`.
- In k6, what happens if you set only a root vus and no iterations, duration or stages?k6 derives a `shared-iterations` scenario and sets `iterations` equal to `vus`, so `k6 run --vus 8 script.js` runs 8 iterations across 8 VUs and exits. It is rarely what the author meant, which is why the flag is usually paired with `-i` or `-d`.
- Can a k6 script keep root iterations and add a scenarios map for a second scenario?No. k6 rejects the combination with *using `iterations` and `scenarios` options simultaneously is not allowed* — the shortcut and the explicit map are mutually exclusive, never merged. Moving to `scenarios` means deleting the root `vus` and `iterations` in the same edit.
saying these in an interview costs you the question
- Says root vus plus iterations gives each VU that many iterations
- Thinks a root duration overrides the iteration budget and times the run
- Expects root iterations and a scenarios map to be merged together
- Assumes the shortcut derives per-vu-iterations rather than shared-iterations
- Believes the derived scenario has no maxDuration ceiling at all