skip to content

Executor Choice

Picking which of k6's six executors schedules a scenario's iterations, and what each option key sets. Interviewers ask because that one string decides whether load is bounded by users or by a clock.

on this pageshow

explore

questions

17

In a k6 `constant-arrival-rate` scenario, what do the `rate`, `timeUnit` and `duration` keys each set?

level: juniorimportance: must knowfreq 74%

answer

  1. three keys, one flat schedule
  2. count, period, and how long
  3. the period the rate applies to
  4. timeUnit defaults to one second
  5. rate counts iteration starts

basics

~10 s

In k6 v2, rate is how many iterations the executor starts during each timeUnit period, timeUnit is that period (default 1s), and duration is how long the scenario keeps starting them.

solid answer

~40 s

In k6 v2, `constant-arrival-rate` describes a flat schedule of iteration starts with three keys. `rate` is an integer count of iterations to start during each period; `timeUnit` is that period and defaults to `'1s'`; `duration` is how long the scenario keeps issuing starts, and it excludes the `gracefulStop` window that follows. So `rate: 100, timeUnit: '1s', duration: '10m'` starts 100 iterations every second for ten minutes. `rate` counts iteration starts, not virtual users and not HTTP requests — a flat 100 requests/s at a search endpoint only follows if one iteration issues exactly one request. `rate` and `duration` are required; k6 exits 104 if either is missing.

code

javascript · 18 lines
javascript
import http from 'k6/http';

export const options = {
  scenarios: {
    search_flat_100: {
      executor: 'constant-arrival-rate',
      rate: 100,
      timeUnit: '1s',
      duration: '10m',
      preAllocatedVUs: 50,
      maxVUs: 200,
    },
  },
};

export default function () {
  http.get('https://example.com/search?q=laptop');
}

go deeper

for a junior

Recall the three keys and say what each one holds: rate is a count of iteration starts, timeUnit is the period that count applies to and defaults to 1s, and duration is how long the scenario keeps starting them.

for a middle

Explain that rate and timeUnit are read as one ratio, so rate 100 per 1s and rate 6000 per 1m are the same schedule, and that rate counts iteration starts rather than requests or users.

for a senior

Show that you check the required keys before a long run, since a missing rate or duration costs a 104 exit rather than a partial result, and that you make one iteration equal one request when the brief is stated in requests per second.

for a principal

Weigh whether the load target should be declared as an arrival rate at all, and who owns the number: a rate written into the scenario block is a contract the team reads, so keep it in one place rather than scattered across environment overrides.

## What `constant-arrival-rate` schedules `constant-arrival-rate` is one of the six executors k6 v2 ships — the others are `shared-iterations`, `per-vu-iterations`, `constant-vus`, `ramping-vus` and `ramping-arrival-rate`. You select it inside the `scenarios` map of the exported `options` object by putting `executor: 'constant-arrival-rate'` on a named scenario. What it schedules is **iteration starts**: k6 plans a fixed number of starts per unit of time and launches each one at its planned instant, for as long as you tell it to. An **iteration** here is one top-to-bottom run of the scenario's `exec` function, which is the script's `default` export unless the scenario names a different one. Exactly three keys describe that schedule, and between them they are the whole of it: `rate`, `timeUnit` and `duration`. ## The three keys, one at a time | key | type | required | default | what it sets | |---|---|---|---|---| | `rate` | integer | yes | — | how many iterations k6 starts during each `timeUnit` | | `timeUnit` | duration string | no | `'1s'` | the period the `rate` count is measured over | | `duration` | duration string | yes | — | how long the scenario keeps starting iterations | - **`rate`** is an integer count of starts, not a fraction. The figure is fixed for the whole scenario: `constant-arrival-rate` defines no key that alters it part-way through, which is precisely the job `ramping-arrival-rate` exists to do. - **`timeUnit`** is only the denominator you choose to write the rate in. k6 reduces `rate / timeUnit` to one arrival rate before scheduling anything, so `rate: 100` with `timeUnit: '1s'` and `rate: 6000` with `timeUnit: '1m'` describe the identical schedule. Its practical use is expressing rates the integer `rate` cannot: one iteration every ten seconds is `rate: 1, timeUnit: '10s'`. - **`duration`** bounds the window during which new starts are issued; it does not include the `gracefulStop` period that follows, during which already-running iterations may finish. It has a floor of one second — k6 reports *"the duration must be at least 1s"* below that. Two further keys, `preAllocatedVUs` (required) and `maxVUs`, tell k6 how large a pool of virtual users it may draw on to serve that schedule. They size the pool that executes the plan; they do not shape the plan, and sizing them is a separate subject from the three keys above. ## Reading a flat 100/s search scenario Suppose the brief is *hold a search endpoint at a flat 100 requests per second for ten minutes*. In k6 v2 that reads out as four decisions: 1. Pick the executor. The rate never changes across the run, so it is `executor: 'constant-arrival-rate'`; `ramping-arrival-rate` is the one whose rate moves. 2. Set `rate: 100` and `timeUnit: '1s'`. Read together they say *start 100 iterations every second*. `timeUnit` could be omitted here, since `'1s'` is its default, but writing it makes the pair self-documenting. 3. Set `duration: '10m'`. After ten minutes k6 stops issuing new starts. 4. Write the `default` function so one iteration issues exactly one request to the search endpoint. Only under that condition does *100 iterations per second* coincide with the *100 requests per second* the brief asked for. While the run is live, k6's description of the scenario opens with the figure it derived from your keys — `100.00 iterations/s for 10m0s` — which is the quickest way to confirm the two keys were read the way you meant them. ## What these three keys do not do - `rate` does **not** set a number of virtual users. It counts starts; how many VUs k6 needs to serve them follows from how long an iteration takes. - `rate` does **not** count HTTP requests. An iteration that issues three requests turns `rate: 100` into roughly 300 requests per second at the endpoint. - `timeUnit` is **not** a batching window. k6 does not release `rate` iterations together at each period boundary; it spaces the starts fractionally across the period. - There is no `stages` key and no `startRate` key on this executor. Both belong to `ramping-arrival-rate`, and k6 will not accept either one here. - Omitting `duration` does not mean *run until interrupted*. It is a missing required option. ## How k6 rejects a bad configuration k6 parses each scenario strictly: any key the selected executor does not define is an unknown field and the whole configuration is refused. Validation then checks the values that were accepted. In k6 v2 both failures surface identically — no iteration runs and the process exits **104** (`InvalidConfig`) — and the messages name the key: - `rate` missing: *"the iteration rate isn't specified"*. - `rate` zero or negative: *"the iteration rate must be more than 0"*. - `duration` missing: *"the duration is unspecified"*. - `timeUnit` zero or negative: *"the timeUnit must be more than 0"*. Because all of this happens before the first iteration, a typo in one of the three keys costs a failed start rather than a wasted ten-minute run. When a scenario refuses to launch, the exit code tells you which kind of problem you have: 104 is your configuration, and any other code is something else entirely.

  • How would you configure a k6 constant-arrival-rate scenario to start one iteration every ten seconds?
    `rate` is an integer, so put the fraction into `timeUnit`: `rate: 1, timeUnit: '10s'`. `rate: 6, timeUnit: '1m'` gives the same schedule, because k6 reduces `rate / timeUnit` to a single arrival rate before it plans anything.
  • What is the shortest duration a k6 constant-arrival-rate scenario accepts?
    One second. Anything below that is rejected during validation with *"the duration must be at least 1s"*, and k6 exits 104 without running an iteration. The same one-second floor applies to `constant-vus`.
  • Does adding a stages array to a k6 constant-arrival-rate scenario make the rate ramp?
    No. `stages` is not a key this executor defines, so k6 treats it as an unknown field, refuses the whole configuration and exits 104. A moving rate needs `ramping-arrival-rate`, which takes `startRate` and `stages` instead of `rate` and `duration`.

saying these in an interview costs you the question

  • Thinks rate sets the number of VUs the scenario runs
  • Reads rate as requests per second whatever the iteration does
  • Believes timeUnit must be seconds and cannot be 1m
  • Adds a stages array to constant-arrival-rate, which has no such key
  • Assumes omitting duration lets the scenario run until interrupted
  • Treats timeUnit as a batch window that releases rate iterations at once
open as a page

Which k6 scenario do the root vus and iterations options build, and what does duration do there?

level: juniorimportance: must knowfreq 68%

basics

~20 s

k6 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.

open as a page

In k6, how do the constant-vus and ramping-vus executors differ, and what options does each take?

level: juniorimportance: must knowfreq 82%

basics

~20 s

k6's constant-vus executor holds a fixed number of VUs for a set time and takes vus plus duration. ramping-vus moves the count through a schedule and takes startVUs, stages and gracefulRampDown. Neither accepts the other's keys.

open as a page

In a k6 arrival-rate scenario, what do preAllocatedVUs and maxVUs control, and what happens when maxVUs is omitted?

level: juniorimportance: must knowfreq 74%

basics

~10 s

preAllocatedVUs is the number of VUs k6 initializes before an arrival-rate scenario starts; maxVUs is the hard ceiling that pool may grow to mid-run. Omitted, maxVUs equals preAllocatedVUs, so the pool never grows.

open as a page

Which keys does k6's `ramping-arrival-rate` executor take, and what does a stage `target` mean?

level: middleimportance: must knowfreq 66%

basics

~20 s

k6 v2's ramping-arrival-rate takes startRate, timeUnit and stages. Each stage is a target plus a duration, and the target is the arrival rate in iterations started per timeUnit that k6 ramps to linearly by the stage's end.

open as a page

In k6, how do the shared-iterations and per-vu-iterations executors differ in spending an iteration budget?

level: middleimportance: must knowfreq 76%

basics

~20 s

k6's shared-iterations executor treats iterations as one total pool that any free VU pulls from, so per-VU counts come out uneven. per-vu-iterations gives every VU that exact count, making the scenario total vus times iterations.

open as a page

In a k6 ramping-vus scenario, what do the duration and target of one stages entry mean?

level: middleimportance: must knowfreq 68%

basics

~20 s

In k6's ramping-vus executor, a stages entry's target is the VU count reached at the end of the stage, and duration is how long the linear move from the current count takes. Repeating the previous target holds that level.

open as a page

When a k6 arrival-rate scenario has no free VU at an iteration's scheduled start, what does k6 do?

level: middleimportance: must knowfreq 68%

basics

~20 s

An arrival-rate start that finds no free VU is abandoned and counted on k6's built-in dropped_iterations counter. If maxVUs headroom remains k6 begins building one more VU in the background; at the ceiling it logs an Insufficient VUs warning.

open as a page

In a k6 ramping-vus run, why are iterations interrupted during ramp-down stages, and what controls it?

level: seniorimportance: must knowfreq 58%

basics

~20 s

k6's ramping-vus executor gives every VU it drops a gracefulRampDown window, 30s by default, to finish the iteration it is already in. A VU still working when the window closes is hard stopped mid-iteration. Setting gracefulRampDown to 0s interrupts immediately.

open as a page

In a k6 `constant-arrival-rate` scenario with `rate: 100` and `timeUnit: '1s'`, when does each iteration start?

level: middleimportance: should knowfreq 48%

basics

~20 s

k6 spaces arrival-rate starts fractionally, not in a burst: it turns rate over timeUnit into one interval, so 100 per second plans a start roughly every 10 ms at fixed offsets from the scenario's start.

open as a page

Why does k6 reject a shared-iterations scenario configured with vus: 20 and iterations: 6?

level: middleimportance: should knowfreq 44%

basics

~10 s

shared-iterations requires iterations to be at least vus, so a pool of 6 leaves 14 of the 20 VUs nothing to claim. k6 fails configuration validation before the run starts and names both numbers.

open as a page

Which executors does k6 derive from the root vus, duration and stages options?

level: middleimportance: should knowfreq 51%

basics

~10 s

k6 rewrites root options into one scenario named default: duration, with optional vus, becomes a constant-vus scenario, and stages, with vus supplying startVUs, becomes ramping-vus. Setting duration and stages together is rejected outright.

open as a page

How do you pick preAllocatedVUs for a k6 constant-arrival-rate scenario targeting 500 iterations per second?

level: middleimportance: should knowfreq 61%

basics

~20 s

Use k6's rule of thumb: preAllocatedVUs is roughly the median iteration duration times the rate, plus headroom. At 500 iterations per second with a 200 ms iteration that is about 100 VUs; then tune until dropped_iterations stays at zero.

open as a page

Your k6 `constant-arrival-rate` scenario sets `rate: 100` but the search endpoint sees 300 requests/s. Why?

level: seniorimportance: should knowfreq 41%

basics

~10 s

k6's rate counts iteration starts, not HTTP requests. Each start runs the whole exec function, so an iteration issuing three calls turns rate 100 into about 300 requests per second at the endpoint.

open as a page

In a k6 shared-iterations scenario, what happens to iterations still unrun when maxDuration expires?

level: seniorimportance: should knowfreq 57%

basics

~20 s

They are never run. k6 stops starting new iterations at maxDuration, which defaults to 10 minutes, lets in-flight ones finish within gracefulStop, and counts the unstarted remainder on the dropped_iterations metric. The run itself does not fail.

open as a page

A k6 ramping-arrival-rate run records many dropped_iterations but never logs an Insufficient VUs warning. Why?

level: seniorimportance: should knowfreq 52%

basics

~20 s

k6 logs the Insufficient VUs warning only once its maxVUs growth budget is exhausted, so its absence means the pool never reached maxVUs. Every start finding no free VU is still dropped while the pool grows.

open as a page

When is setting maxVUs above preAllocatedVUs in a k6 arrival-rate scenario worth its cost?

level: principalimportance: should knowfreq 43%

basics

~20 s

Rarely - k6 builds each VU above preAllocatedVUs mid-run by re-running the init context on the machine already generating load, and in Grafana Cloud maxVUs is what counts against the subscription. Reserve it for first-time sizing.

open as a page