skip to content

Should a team standardise on a k6/experimental module, and how would you limit the blast radius?

level: principalimportance: nice to knowfreq 34%

answer

  1. the guarantee, not the code quality
  2. excluded from the published allowlist
  3. minors may change it, majors move it
  4. one import site, not fifty

basics

~20 s

Yes when no core k6 module does the job, no when one does. k6 excludes experimental paths from its stability allowlist, so contain the exposure: pin the k6 version and funnel the import through one shared local module.

solid answer

~50 s

The decision is about k6's guarantee, not about code quality. k6 puts core modules on a published allowlist whose signatures cannot break outside a major release, and names `k6/experimental/` paths as excluded, so a change can land in a minor -- and k6 ships minors roughly every six weeks. Adopt one when there is no core equivalent, which is the actual situation for all three that remain: CSV parsing, incremental file access and streams have no core counterpart. Then contain it. Pin the k6 version your suite runs rather than tracking the newest. Import the experimental path in **one** local module that every script imports, so graduation is a one-line edit instead of a hundred. And keep a scheduled run against the newest k6 so a break surfaces on your calendar rather than on release day.

code

javascript · 6 lines
javascript
// lib/csv.js - the one place the experimental path is named
export { parse, Parser } from 'k6/experimental/csv';

// every script imports the local module instead:
//   import { parse } from './lib/csv.js';
// graduation then costs one edit rather than one per script

go deeper

for a junior

Know that a k6 experimental import works with no setup, and that the prefix is a signal about future changes rather than about whether the module is usable today.

for a middle

Explain that k6's allowlist excludes experimental paths, so a change may arrive in a minor, and that graduation moves the module to a core path your scripts have to name.

for a senior

Show the containment moves: a pinned k6 version, one import site for the experimental path, a scheduled run against the newest release, and an inventory for the next major.

for a principal

Frame it as a written team standard with a stated condition for adoption, an owner for the inventory, and a plan for the k6 major upgrade rather than a case-by-case judgement.

## What you are actually agreeing to k6's versioning document is an allowlist: it names what is guaranteed, and says anything not named is not covered. Core modules are named. Experimental ones, "recognisable from their `k6/experimental` prefixed import path", are explicitly excluded. So adopting one is a decision to take a dependency k6 has told you in writing it may change. Two facts set the size of that exposure: - **k6 ships a minor roughly every six weeks.** A breaking change to an experimental module is allowed in any of them, without a major version bump to warn you. - **k6 ships a major roughly once a year**, and that is when graduation finally bites: the module moves to a core path, the experimental path is deprecated, and at a later major the old path becomes a stub that throws. `k6/experimental/browser` is exactly that today. What the prefix does **not** mean is that the module is unmaintained, unsupported, or unfit for a pipeline that gates a release. k6 states that experimental modules keep a high level of stability and receive regular maintenance and security work. ## When the answer is yes The honest test is whether a core module does the same job. For the three modules k6 v2 still ships under the prefix, it does not: - `k6/experimental/fs` gives a file handle you can read incrementally, which is a different thing from loading a fixture whole in the init context. - `k6/experimental/csv` parses records out of that input. - `k6/experimental/streams` provides the Streams API primitives the other two compose with. If your test data is large enough that these matter, "avoid experimental modules" is not advice, it is a decision to not run the test. Take the dependency and manage it. ## When the answer is no Say no when a core module already covers the need, and say no when the experimental module is convenience rather than capability. Every experimental path you adopt is one more item on the list you must revisit at the next k6 major, and that list is the real cost -- not the module. Two refinements make the judgement sharper than a blanket rule: - **Ask how reversible the adoption is.** A module used behind one helper is a cheap bet. A module whose types thread through every fixture-loading path in the suite is not, and the prefix is exactly the wrong place to accept that shape of coupling. - **Note the counterintuitive ranking.** A *deprecated* k6 path is a safer dependency than an *experimental* one: deprecation is guaranteed for the rest of the major line, while an experimental module carries no such promise. The loud thing is the safe thing here, and teams routinely get this backwards because a warning feels worse than silence. ## Containment 1. **Pin the k6 version the suite runs.** "Latest" is a moving target for exactly these paths and for nothing else in the namespace, because everything else is protected until a major. 2. **Import the experimental path in one place.** A single local module that re-exports what your scripts need turns graduation into one edit. Fifty scripts importing `k6/experimental/csv` directly turns it into fifty. 3. **Run the suite against the newest k6 on a schedule.** The point is to learn about a change on a day you chose, rather than on the day someone bumps the pinned version under deadline. 4. **Keep an inventory.** Write down which experimental paths the suite depends on. A grep produces it in seconds and it is the entire input to the next major upgrade. 5. **Migrate to the core path on graduation, not later.** Once the module graduates, the core path is the one on the allowlist; staying on the experimental alias keeps you outside the guarantee for no benefit and puts you on a deprecation clock. ## What graduation day actually looks like It is not an outage. The graduated module appears at a core path; the old path becomes a deprecated alias that logs one notice per k6 process and keeps working for the rest of that major line. So a team that does nothing has, in practice, until the next major -- roughly a year. A team that funnelled the import through one module spends five minutes. A team that scattered it and ignores warnings finds out at the major bump, when the alias stops resolving and the run no longer starts. ## The standard worth writing down Two sentences are usually enough for a team policy: experimental k6 modules are allowed where no core module does the job, and every experimental import goes through the shared module rather than into a script directly. That gives you the capability without the scatter, and it makes the next k6 major a scheduled edit instead of an archaeology exercise.

  • Is there a core k6 alternative to k6/experimental/fs?
    Not for the same job. The module exists to give a file handle you can read a piece at a time, which the init-context file API does not offer. That is why it is worth adopting despite the prefix -- refusing it means not running the test at all.
  • What is the strongest argument against adopting an experimental k6 module?
    That a breaking change is permitted in a minor k6 ships roughly every six weeks, and your suite is what goes red. The counter-argument is that the same policy makes the break loud and dated rather than silent, which is easier to plan around than an undocumented change.
  • How does a k6 module graduation actually reach your scripts?
    As an import-path edit. The module is re-registered under a core path, the experimental path becomes a deprecated alias for the rest of the major, and at a later major it becomes a stub that throws. Scripts that name the path directly each need the edit.

saying these in an interview costs you the question

  • Rejects experimental k6 modules on principle without checking for a core one
  • Adopts one while tracking the newest k6 with no pinned version
  • Thinks graduation is transparent and needs no edit in the scripts
  • Assumes a core k6 module already covers csv, fs and streams
  • Treats the experimental prefix as meaning unmaintained or unsupported