In k6 v2, which module paths still live under k6/experimental/, and what does that prefix mean?
answer
- a versioning promise, not a feature flag
- excluded from the published stability allowlist
- the list got very short in v2
- file handles, records, and streaming primitives
basics
~20 sk6 v2 ships exactly three experimental modules: k6/experimental/csv, k6/experimental/fs and k6/experimental/streams. The prefix marks a module deliberately left outside k6's stability guarantee, so it may change in a minor release; every other importable path is core.
solid answer
~40 sk6 v2 registers exactly three paths under the experimental prefix: `k6/experimental/csv`, `k6/experimental/fs` and `k6/experimental/streams`. Everything else you can import from a stock binary is a core module -- `k6`, `k6/http`, `k6/browser`, `k6/net/grpc`, `k6/websockets`, `k6/ws`, `k6/execution`, `k6/metrics`, `k6/data`, `k6/crypto`, `k6/crypto/x509`, `k6/encoding`, `k6/html`, `k6/secrets` and `k6/timers`. The prefix is not a feature flag: nothing has to be enabled, no CLI option unlocks it, and importing one of the three prints no warning. It is a statement about versioning. k6's stability policy puts core modules on an explicit allowlist that cannot break outside a major release and explicitly excludes anything under `k6/experimental/`, so those three may change in an ordinary minor and will move to a core path if they stabilise.
code
javascript · 9 linesimport http from 'k6/http';
import { parse } from 'k6/experimental/csv';
import { open } from 'k6/experimental/fs';
import { ReadableStream } from 'k6/experimental/streams';
export default function () {
// core and experimental imports resolve the same way; no flag enables the prefix
console.log(typeof http, typeof parse, typeof open, typeof ReadableStream);
}go deeper
Be able to say that k6 v2 has only three experimental modules and that the prefix is part of the import path rather than a switch you turn on. Naming csv, fs and streams is enough at this level.
Explain that the prefix marks exclusion from k6's published stability allowlist, so the module may change in an ordinary minor release, and that graduation re-registers it under a core path.
Show that you know which paths in your own scripts are experimental and what happens on graduation day, rather than discovering the change from a red pipeline after a k6 upgrade.
Weigh what an experimental k6 module buys you against a break landing in a six-weekly minor, and decide explicitly what your team is allowed to depend on and how that is contained.
## What the prefix actually is k6 resolves every import specifier that begins with `k6/` against a registry compiled into the binary, not against the filesystem. That registry is a flat map from import path to module, and in k6 v2 each entry falls into one of a handful of statuses. `k6/experimental/` is a naming convention applied to the entries the k6 team has not yet committed to keeping stable. Two things it is **not**: - It is **not a feature flag.** No CLI option, environment variable or `options` key has to be set before an experimental import resolves. It works out of the box exactly like `k6/http` does. - It is **not a quality warning.** Importing one of the three prints nothing at all. Experimental modules in k6 are maintained and supported like the rest of the binary; what is missing is the *promise* about their shape. ## The three experimental modules in k6 v2 | path | what it covers | |---|---| | `k6/experimental/csv` | parsing CSV input into records, with `parse` and a `Parser` class | | `k6/experimental/fs` | file access via `open()` and `SeekMode`, shared across VUs | | `k6/experimental/streams` | a Streams API implementation: `ReadableStream`, `WritableStream` and friends | That list is short because k6 v2.0.0 was a clean-out release. The `k6/experimental/` namespace used to be much larger, and most of what was in it either graduated to a core path or left the binary altogether -- which is why a script copied from a v0.5x tutorial so often names a path that no longer resolves. ## The core modules Everything else a stock v2 binary can import is core: `k6`, `k6/browser`, `k6/crypto`, `k6/crypto/x509`, `k6/data`, `k6/encoding`, `k6/execution`, `k6/html`, `k6/http`, `k6/metrics`, `k6/net/grpc`, `k6/secrets`, `k6/timers`, `k6/websockets` and `k6/ws`. Two of these -- `k6/ws` and `k6/crypto` -- are documented as superseded by a newer API (`k6/websockets` and the global `crypto` object respectively), but "superseded" is a recommendation, not a status change: both are still core, still import without a warning, and are still covered by the guarantee below. ## What "excluded from the stable API surface" costs you k6 follows semantic versioning and publishes an explicit allowlist of what it guarantees. Core modules are on it -- "any class, properties, methods, function, or relative signature that is part of the module and is publicly exposed and documented". Experimental modules, recognisable by the prefix, are named as excluded. In practice: 1. A core module's published signature cannot break outside a **major** release, and k6 ships a major roughly **once a year**. 2. k6 ships a **minor about every six weeks**, and an experimental module is allowed to change in one of those. Your suite is what goes red. 3. When an experimental module stabilises it **graduates**: it is re-registered under a core path, and the old experimental path is deprecated and then deleted. That deletion is an import-path edit in every script that used it. 4. Deprecation is not instant death -- a deprecated API is guaranteed for the lifetime of the major version it was deprecated in. ## The statuses that are neither core nor experimental Two more categories exist in the same namespace, and confusing them with "experimental" is the usual mistake: - **Removed.** Six old `k6/experimental/` paths are still registered names in k6 v2, but each is bound to a stub whose only behaviour is to throw a message naming the replacement: `k6/experimental/browser`, `k6/experimental/grpc`, `k6/experimental/timers`, `k6/experimental/webcrypto`, `k6/experimental/tracing` and `k6/experimental/redis`. A seventh, `k6/experimental/websockets`, is merely deprecated: it logs a notice and still works. - **Extension.** Anything under `k6/x/` comes from an extension rather than the core binary; k6 refuses to register an external module under any other prefix. A stock binary does not resolve `k6/x/` paths at all. So "is this path experimental?" has a precise answer in k6 v2, and the honest one is that only three paths qualify. If a path you are looking at starts with `k6/experimental/` and is not one of those three, it is not experimental -- it is deprecated, removed, or something you invented. ## Checking rather than remembering The list moves between majors, so treat any list you memorised as dated. Three ways to check, in increasing order of authority: - The k6 documentation's JavaScript API page enumerates the core modules, and its `k6/experimental` page lists what is currently under the prefix. - The binary itself is the arbiter. If a path resolves with no log line and does not carry the prefix, it is core; if it resolves with no log line and does carry the prefix, it is one of the three. - A path that fails is telling you its status in the error text -- a migration message means removed, an unknown-modules error means the name was never registered. For an interview, the useful shape of the answer is: name the three, say the prefix is a versioning statement rather than a switch, and note that the namespace shrank sharply at v2.0.0.
- Does k6 print a warning when a script imports k6/experimental/csv?No. In k6 v2 all three experimental paths resolve straight to their modules with no log line at all. The only path under the prefix that warns is `k6/experimental/websockets`, which is deprecated in favour of `k6/websockets`. The rest of the old experimental namespace throws rather than warns.
- What happens to the old path when an experimental k6 module graduates?It is re-registered under a core path, and the experimental one is kept for a while as a deprecated alias before being deleted at a major. In k6 v2 the deleted ones are still registered names bound to a stub that throws a message naming the replacement.
- How often can an experimental k6 module change under k6's own policy?k6 ships a minor about every six weeks and a major about once a year. Core module signatures are protected from breaking changes until a major; experimental modules are explicitly excluded from that allowlist, so a breaking change may land in any minor.
saying these in an interview costs you the question
- Thinks the experimental prefix means a flag must be enabled first
- Assumes k6/experimental/browser is still an experimental module
- Calls experimental k6 modules unmaintained prototypes unfit for real tests
- Counts every k6/experimental path as importable in v2
- Confuses k6/ws being superseded with k6/ws being experimental