skip to content

Peer Comparison

Saying honestly what a scripted, single-binary generator buys a team and what it costs against the other load runners. Interviewers want judgement here rather than a recited feature list.

on this pageshow

explore

questions

4

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%

answer

  1. the test is not a document
  2. code review, not plan editing
  3. imports, exported options, default function
  4. JavaScript skills required to author
  5. looks like Node, is not Node

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.

solid answer

~50 s

k6 has no plan document and no authoring GUI — the test *is* a JavaScript (or, in k6 v2, TypeScript) module that the binary loads. Its configuration is an ordinary exported `options` object, so the run's shape lives in the same file as the request code, travels through the same pull request, and produces a line-level diff a reviewer can argue with. Reuse is plain ES `import`, so a team can share auth helpers or a common options fragment as a module. The costs are real: whoever authors or reviews a test has to read JavaScript, there is nothing for a non-programmer to point and click at, and the script's runtime only *looks* like Node — it is k6's own embedded engine, so npm packages that reach for Node built-ins do not run. Configuration mistakes also surface when the run starts rather than as form validation while you type.

code

javascript · 13 lines
javascript
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 10,
  duration: '30s',
};

export default function () {
  const res = http.get('https://quickpizza.grafana.com');
  check(res, { 'status is 200': (r) => r.status === 200 });
  sleep(1);
}

go deeper

for a junior

Remember the shape: a k6 test is a JavaScript module with imports, an exported options object and an exported default function. There is no separate plan file and no built-in visual editor.

for a middle

Explain the consequences of that shape — the configuration diffs alongside the request code, shared helpers arrive by ES import, and the script's engine is not Node, so most npm packages are unavailable.

for a senior

Weigh it for a real team: who authors, who reviews, whether a shared module layer exists, and whether logic unrelated to load generation is creeping into test files. Say what review rules you would add.

for a principal

Frame the choice as an ownership decision. Making the test source code moves load testing into the engineering workflow and out of a specialist's hands; decide whether your organisation wants that shift before you pick the tool.

## The artefact is a JavaScript module A k6 test is not a document that a tool opens and edits; it is a **JavaScript module** that the k6 binary loads and executes. In k6 v2 a `.ts` file works the same way — types are stripped before execution. The module has three parts a reviewer can point at: 1. `import` statements pulling in k6's own modules (`k6/http`, `k6` itself, and so on). 2. An **exported `options` object** carrying the run's configuration. 3. An **exported default function** that k6 calls once per iteration. ```javascript import http from 'k6/http'; import { check, sleep } from 'k6'; export const options = { vus: 10, duration: '30s', }; export default function () { const res = http.get('https://quickpizza.grafana.com'); check(res, { 'status is 200': (r) => r.status === 200 }); sleep(1); } ``` That is the whole test. There is no companion file the tool maintains for you, and no editor you are expected to open it in. ## What the model makes easy - **It reviews like code.** The run's configuration and its request logic sit in one text file, so both arrive in the same pull request and both get the same scrutiny. A reviewer can see that a duration changed at the same time as a header did. - **Configuration is an ordinary object.** `options` is exported JavaScript, so it can be assembled from constants, spread from a shared fragment, or switched on an environment variable — the same techniques the team already uses in application code. - **Reuse is `import`.** A shared authentication helper, a base URL, or a house set of tags becomes a module that several tests import, rather than something copied between saved plans. - **Merges are line-level.** Two engineers touching the same test on separate branches get a normal three-way merge, because the artefact is plain text with meaningful lines. - **Existing skills transfer.** A team that writes JavaScript daily does not learn a second authoring vocabulary before it can write its first useful test. ## What it costs - **There is no author for a non-programmer.** A QA specialist who does not write code cannot assemble a run by hand; every test is code, and every review of a test is a code review. - **It looks like Node, and it is not.** k6 embeds its own JavaScript engine and exposes no Node API surface, so an npm package that touches the filesystem, sockets or Node globals will not run inside a test. "We can just reuse our existing helpers" is the assumption that most often breaks on day one. - **Configuration errors surface at run time.** Nothing validates the shape of `options` while you type. A mistyped key is caught when k6 parses the script, not while you are writing it — and how loudly it is caught depends on where the key sits. - **Programming freedom cuts both ways.** Because the test is a general-purpose program, it can grow logic that has nothing to do with generating load. Nothing in the tool stops that; only review does. ## The trade-off in one table | dimension | k6's JS-module model | what you give up | |---|---|---| | authoring | write code in the editor you already use | no point-and-click authoring for non-coders | | review | one text diff covering logic and configuration | reviewers must be able to read the language | | reuse | ES `import` of shared modules | you build that shared layer yourself | | ecosystem | k6's own modules, always available | no Node API surface, so most npm packages are out | | validation | errors reported when the script is parsed | no editor-side schema checking as you type | ## Choosing it for a JS-fluent team For a team that already writes JavaScript, this model is the strongest single argument for k6: the test stops being a separate artefact owned by a separate person and becomes another module in a repository, with the same review, the same branch protection, and the same history. Before committing, check three things: 1. **Who will author tests.** If people without programming skills need to build runs unaided, this model works against you and no amount of tooling hides it. 2. **What you expect to import.** List the libraries the team assumes it will reuse and confirm they are pure JavaScript with no Node dependency. 3. **Where the shared layer will live.** Decide up front which repository holds the modules every test imports, or each team will grow its own copy. The model is a genuine trade: you gain everything that comes from treating a load test as source code, and you take on everything that comes from it being source code.

  • A colleague wants to reuse an npm package the team already maintains inside a k6 test. What do you check first?
    Whether it is pure JavaScript. k6 runs its own embedded engine with no Node API surface, so a package that imports Node built-ins, opens files or uses Node globals will not load. Pure-JS utilities — formatting, signing, data shaping — usually work; anything reaching for the platform does not.
  • Does k6's model give you anything once the test is written, or only while authoring it?
    Mostly afterwards. Because the test is source, it gets history, blame, branch protection and review on every change, so a run's configuration is never edited by someone in a UI without a trace. That auditability is usually worth more over a year than the authoring convenience is in week one.
  • Your team is JS-fluent but the QA group is not. How do you split the work?
    Have the JS-fluent side own a shared module layer — auth, base URLs, tagging, a house options fragment — so a test file reduces to a few lines of intent. QA then reviews and parameterises those thin files rather than authoring request logic from scratch.

saying these in an interview costs you the question

  • Claiming a k6 test is a configuration file the tool generates for you
  • Assuming npm packages work because the script is JavaScript
  • Saying non-programmers can author k6 runs through a built-in editor
  • Treating the exported options object as documentation rather than the run's real configuration
  • Believing configuration must be repeated in every test file rather than imported
open as a page

Why can a k6 run gate a CI pipeline with no extra tooling, and where does that native gate stop?

level: seniorimportance: should knowfreq 55%

basics

~20 s

k6 declares its pass rule in the script's exported options and exits 99 when a threshold is breached, so the CI step is just the run. But a failed check() never changes that code, and a script with no thresholds exits zero.

open as a page

Rolling k6 out to several teams, what must you standardise because a k6 test is ordinary JavaScript?

level: principalimportance: should knowfreq 42%

basics

~20 s

Standardise the binary every runner resolves to, the shared module layer teams import, and a rule that every test declares thresholds, since k6 exits zero when none exist. The executor vocabulary standardises itself: only six names are legal.

open as a page

In k6, what does an import from the k6/x/ namespace imply for the binary your team and CI must run?

level: seniorimportance: nice to knowfreq 38%

basics

~20 s

The script cannot run on a stock k6 release. Extensions are compiled into the binary under the k6/x/ prefix, so what the team pins and distributes is a specific k6 build, not just a script and a version.

open as a page