skip to content

k6

The scriptable load tester where scenarios are JavaScript and pass/fail is expressed as thresholds on metrics. Asked because it fits load testing into CI, which is where interviewers want performance checks to live.

on this pageshow

explore

questions

161 · 9 sections

In k6, what happens to the running iteration when a check() condition evaluates to false?

level: juniorimportance: must knowfreq 74%
basics
~10 s

Nothing halts. k6 records the failure on its built-in checks metric, check() returns false, and the iteration carries straight on to the next statement. The run's exit status is unaffected.

open as a page

In k6, how do you call check() from the k6 module, and what does each argument do?

level: juniorimportance: must knowfreq 78%
basics
~20 s

k6's check(), from the k6 module, has the signature check(val, sets, [tags]): a value, an object whose keys are check names and whose values are conditions called with that value, and optional extra tags. It returns a boolean.

open as a page

In k6, what exit code does a run return when one of its thresholds is breached?

level: juniorimportance: must knowfreq 72%
basics
~20 s

k6 exits with code 99 when at least one threshold is breached, and 0 when they all hold. That single integer is the whole machine-readable verdict a CI job reads; the printed summary is for humans.

open as a page

In k6, why can a threshold of `checks: ['rate>90']` never pass, however many checks succeed?

level: juniorimportance: must knowfreq 72%
basics
~20 s

k6's built-in checks metric is a Rate, and the only aggregation a Rate threshold accepts is rate, which is a fraction from 0.00 to 1.00 rather than a percentage. So rate>90 is unreachable; write rate>0.9.

open as a page

In k6, what does a threshold key like http_req_duration{status:200} do that a plain metric name does not?

level: juniorimportance: must knowfreq 62%
basics
~10 s

The braces create a sub-metric: k6 registers a filtered copy of http_req_duration that receives only the samples whose tags contain status:200, and evaluates the threshold against that copy instead of the whole metric.

open as a page

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

level: juniorimportance: must knowfreq 74%
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.

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 a k6 script, what does the default exported function do, and what counts as one iteration?

level: juniorimportance: must knowfreq 84%
basics
~20 s

k6's default exported function is the VU code: one virtual user runs it from its first line to its last, and that single start-to-finish call is one iteration. When it returns, the VU calls it again.

open as a page

In a k6 script, which code runs in the init context, and how often does it run?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Everything outside a k6 lifecycle function is init code: imports, the exported options object, open() calls, metric constructors. k6 runs it once per virtual user, in that VU's own JavaScript runtime, before that VU's first iteration.

open as a page

In a k6 script, when does setup() run and how does its return value reach the other stages?

level: juniorimportance: must knowfreq 78%
basics
~20 s

k6 calls setup() once per test run, after the init stage and before any virtual user starts. Whatever it returns is JSON-encoded once and handed to the default function and to teardown() as their first argument.

open as a page

What does k6's SharedArray from k6/data change about how a data file is held in memory?

level: juniorimportance: must knowfreq 76%
basics
~20 s

k6's SharedArray holds one copy of a data set per k6 process, not one per VU. Its loader runs once, k6 stores each element as a JSON string, and a VU gets a copy only on index access.

open as a page

Which k6 calls throw when placed in a script's init context, and what do they all have in common?

level: middleimportance: must knowfreq 66%
basics
~10 s

Anything needing VU state throws in k6's init context: http requests and batch, new http.CookieJar(), check(), group(), a custom metric's .add(), and exec.vu, exec.instance or exec.test.options. k6 attaches VU state only after init finishes.

open as a page

In k6, what is the exported `options` object and how does it configure a test run?

level: juniorimportance: must knowfreq 82%
basics
~20 s

k6 has no separate configuration file format. A k6 script exports an object named options, k6 reads it once at init, and its root keys - vus, duration, stages, scenarios, thresholds, tags - become the run configuration.

open as a page

In a k6 script, what do the keys of the `options.scenarios` object mean, and what must each entry declare?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Every key in k6's options.scenarios object is that scenario's name, unique within the script and limited to letters, digits, underscores and dashes. Each entry must declare executor; exec, startTime, gracefulStop, env and tags all have defaults.

open as a page

In k6, which five layers can set the same option, and in what order do they override each other?

level: middleimportance: must knowfreq 70%
basics
~10 s

k6 resolves each option through five layers, lowest to highest: built-in defaults, a JSON config file, the script's exported options, a K6_ environment variable, then the command-line flag. The CLI flag always wins.

open as a page

In k6, why does adding --duration on the command line discard a whole scenarios map the script declared?

level: seniorimportance: must knowfreq 58%
basics
~10 s

Because duration, iterations, stages and scenarios form one execution group in k6: any of the four set in a higher layer clears all four from every lower layer before the new value is applied.

open as a page

In a k6 scenarios map, what is `startTime` measured from, and how do you make two scenarios run back to back?

level: seniorimportance: must knowfreq 64%
basics
~20 s

startTime is an absolute offset from the start of the k6 run, not from the previous scenario's end. k6 launches every scenario at once and each waits out its own offset, so sequencing is arithmetic you do yourself.

open as a page

Which of k6's four metric types does each built-in such as vus, http_reqs or checks use?

level: juniorimportance: must knowfreq 66%
basics
~20 s

k6 has four metric types: Counter, Gauge, Rate and Trend. Among the built-ins, vus and vus_max are Gauges, http_reqs and iterations are Counters, checks and http_req_failed are Rates, and every duration such as http_req_duration is a Trend.

open as a page

Which four metric classes does k6's k6/metrics module export, and what does each keep?

level: juniorimportance: must knowfreq 76%
basics
~20 s

k6/metrics exports Counter, Gauge, Rate and Trend. Counter sums added values and reports count and rate; Gauge keeps the last value; Rate reports the share of non-zero values; Trend keeps every value, giving avg, min, max, med and p(N).

open as a page

In k6, what does wrapping requests in group('name', callback) add to the metrics they emit?

level: juniorimportance: must knowfreq 70%
basics
~10 s

k6 tags every sample emitted inside the callback with a group tag holding the full nested group path joined by ::, and it emits one group_duration Trend sample timing the callback.

open as a page

In k6, which three metrics add up to http_req_duration, and what does it leave out?

level: middleimportance: must knowfreq 74%
basics
~10 s

http_req_duration equals http_req_sending plus http_req_waiting plus http_req_receiving. It excludes http_req_blocked, http_req_connecting and http_req_tls_handshaking, so connection setup never appears in it.

open as a page

In k6, what happens if you construct a k6/metrics Trend inside the default function instead of at module scope?

level: middleimportance: must knowfreq 64%
basics
~10 s

Constructing a k6 custom metric outside the init context throws "metrics must be declared in the init context". Only .add() may run inside an iteration; the k6/metrics constructors must sit at module scope.

open as a page

In k6 v2, what happens to a script that imports k6/experimental/browser, and what replaces it?

level: juniorimportance: must knowfreq 62%
basics
~10 s

The import throws straight away with a migration message: in k6 v2 the browser module has graduated and k6/experimental/browser was removed. Import browser from k6/browser instead, and await its calls.

open as a page

In k6 v2, which module provides the gRPC client, and what happens if a script imports k6/experimental/grpc?

level: juniorimportance: must knowfreq 58%
basics
~20 s

k6 v2 ships its gRPC client at the stable path k6/net/grpc. The old k6/experimental/grpc name is registered only to throw a migration error on import, so the run aborts in the init phase before any VU starts.

open as a page

In k6, how do you send a JSON body with http.post(), and what does a plain object send instead?

level: juniorimportance: must knowfreq 76%
basics
~10 s

k6 picks the encoding from the body's JavaScript type: a plain object is form-encoded as application/x-www-form-urlencoded. For JSON, pass JSON.stringify(payload) as the body and set Content-Type in the params headers object.

open as a page

In k6, which scenario option enables a real browser, and where in the options object does it go?

level: middleimportance: must knowfreq 58%
basics
~10 s

Set type to 'chromium' in a scenario's own options.browser block, so the full path is options.scenarios.<name>.options.browser.type. It is per-scenario, there is no root-level browser option, and 'chromium' is the only value k6 v2 accepts.

open as a page

Which k6/net/grpc Client calls must run in the init context, and which are rejected there?

level: middleimportance: must knowfreq 62%
basics
~20 s

client.load() and client.loadProtoset() are init-only and error elsewhere with "load must be called in the init context". client.connect(), invoke(), asyncInvoke() and close() are the reverse: they raise an init-context error and must run inside an iteration.

open as a page

In k6, what must an exported `handleSummary(data)` function return, and where does each entry go?

level: juniorimportance: must knowfreq 72%
basics
~20 s

An object whose keys are destinations and whose values are strings or ArrayBuffers. k6 sends the key stdout to standard output, stderr to standard error, and treats every other key as a file path it creates or overwrites.

open as a page

In k6, how do you choose where a run streams its metrics, and which `--out` targets does v2 accept?

level: middleimportance: must knowfreq 58%
basics
~20 s

k6 picks streaming destinations with the repeatable -o/--out flag or the K6_OUT environment variable. k6 v2 accepts json, csv, cloud, influxdb, experimental-prometheus-rw, opentelemetry, experimental-opentelemetry and web-dashboard; any other name aborts the run before it starts.

open as a page

Which statistics can k6's summaryTrendStats option list, and what does it print by default?

level: middleimportance: must knowfreq 58%
basics
~10 s

k6's summaryTrendStats accepts avg, min, med, max, count and p(N) for N between 0 and 100. It defaults to avg, min, med, max, p(90), p(95), and any list you set replaces that default entirely.

open as a page

What does k6's `--out json=` write to its file, and how does `--out csv=` differ?

level: juniorimportance: should knowfreq 50%
basics
~20 s

k6's json target writes newline-delimited objects: a Metric declaration, then a Point per sample with time, value and tags. The csv target writes a fixed header of metric_name, timestamp and metric_value, then tag columns. Both gzip on a .gz path.

open as a page

What does k6's summaryTimeUnit option change in the end-of-test summary?

level: juniorimportance: should knowfreq 40%
basics
~20 s

k6's summaryTimeUnit fixes the unit every duration is printed in throughout the end-of-test summary. It accepts only s, ms or us; left unset, k6 picks a readable unit per value instead, so columns may mix ns, us, ms and s.

open as a page

Why does a k6 script's import of './helpers' fail when './helpers.js' works?

level: juniorimportance: must knowfreq 72%
basics
~20 s

k6 resolves import specifiers the way a browser does, not the way Node does: it never appends .js, never falls back to index.js and never searches node_modules. The extension-less path names a file that does not exist, so the load fails.

open as a page

Why does importing k6/experimental/browser abort a k6 v2 run, and what replaces it?

level: juniorimportance: must knowfreq 71%
basics
~20 s

The browser module graduated to k6/browser, and k6 v2 keeps the old path registered only as a stub that throws a migration message. The run dies while the script is loading and k6 exits 107.

open as a page

Why does adding a new protocol to k6 require a compiled custom binary rather than a plugin file?

level: middleimportance: must knowfreq 72%
basics
~10 s

k6 extensions are Go code compiled into the k6 binary; k6 has no runtime plugin loader. Either k6 provisions a prebuilt binary for you automatically, or you build one yourself with xk6 build --with.

open as a page

Why does a k6 test script that imports Node's fs module fail before any VU runs?

level: middleimportance: must knowfreq 72%
basics
~20 s

k6 executes JavaScript on Sobek, a JavaScript engine written in Go, not on Node.js. It ships no Node standard library and no node_modules resolution, so a bare specifier like fs never resolves and loading the script fails during init.

open as a page

How does k6's own require() differ from an ES import statement in a test script?

level: middleimportance: must knowfreq 51%
basics
~20 s

k6 accepts both, but require() is k6's own implementation, not Node's: it loads built-in k6 modules, local files and remote https scripts only, it exists solely in the init stage, and it takes a specifier computed at runtime.

open as a page

Why does running the grafana/k6 image look like `docker run -i grafana/k6 run - < script.js`?

level: juniorimportance: must knowfreq 62%
basics
~20 s

The grafana/k6 image sets ENTRYPOINT ["k6"], so appended arguments start at a k6 subcommand - here, run. The script lives on the host and not in the image, so the filename - makes k6 read it from standard input.

open as a page

What do k6's --execution-segment and --execution-segment-sequence flags do, and why pass both?

level: middleimportance: must knowfreq 68%
basics
~20 s

In k6, --execution-segment names the slice of total work one process runs, and --execution-segment-sequence names the full partition every process shares. Pass both, or each instance invents its own partition and the slices stop lining up.

open as a page

A script piped into grafana/k6 with `run -` fails on a relative import - why, and what fixes it?

level: middleimportance: must knowfreq 54%
basics
~20 s

Piping delivers one file and nothing else. k6 records a stdin script as /-, so relative imports resolve against the container's working directory, not the script's folder. Mount the directory and pass an in-container path instead.

open as a page

For a JS-fluent team, what does k6's script-as-a-JavaScript-module model make easy, and what does it cost?

level: middleimportance: must knowfreq 62%
basics
~20 s

A k6 test is a JavaScript module: imports, an exported options object, a default function. It reviews, diffs and merges like application code. The cost is that authoring and review require JavaScript, and the runtime is not Node.

open as a page

After four k6 instances each run one execution segment, what does core k6 not do for you?

level: seniorimportance: must knowfreq 62%
basics
~10 s

Core k6 divides the plan but never rejoins the results. There is no primary process, each instance evaluates its thresholds against only its own samples, and each writes its own output stream and summary.

open as a page