What happens when a k6 v2 run is started with `-o kafka`, `-o statsd` or `-o datadog`?
answer
- the names resolve, the constructors refuse
- three removals, two different versions
- the error points outside the binary
- removed in v0.34.0 and v0.55.0
- one of the three is still listed
basics
~20 sAll three names still resolve in k6 v2, but their constructors do nothing except return a migration error naming an xk6 output extension, so the run aborts before any virtual user starts. kafka and datadog were removed in v0.34.0, statsd in v0.55.0.
solid answer
~40 sThey fail, and they fail deliberately. `kafka`, `statsd` and `datadog` are still present in k6's built-in output list, but each one's constructor only returns an error pointing at the xk6 output extension that replaced it — so k6 aborts while building outputs, before a single virtual user starts. `kafka` and `datadog` were removed in v0.34.0 and `statsd` in v0.55.0. The names survive so that an old command gives a useful migration message instead of a bare `invalid output type`. There is a listing quirk worth knowing: the "available types" list k6 prints for an unknown name hides `kafka` and `datadog` but still shows `statsd`, even though selecting it fails.
code
bash · 10 lines# resolves, then aborts while constructing the output
k6 run -o statsd script.js
# a genuinely unknown name gets a different message, and the
# list it prints hides kafka and datadog but still shows statsd
k6 run -o graphite script.js
# what a stock k6 v2 binary can actually stream to
K6_PROMETHEUS_RW_SERVER_URL=http://prom:9090/api/v1/write \
k6 run -o experimental-prometheus-rw script.jsgo deeper
Just recall that kafka, statsd and datadog are not usable output names on a current k6, and that trying one stops the run immediately rather than degrading it.
Explain the mechanism: the names still resolve, their constructors return a migration error naming an xk6 extension, and k6 aborts while building outputs rather than mid-run.
Show you would spot this on a version bump in CI, read the migration text, and choose between building a custom binary and repointing the run at a supported destination.
The angle to argue is dependency: an output that lives in an extension means owning a build of k6, so weigh that against moving the estate onto a destination the stock binary supports.
## Three names that resolve and then refuse `kafka`, `statsd` and `datadog` are all still spellable in k6 v2. Each one is present in k6's built-in output enumeration **and** in the map of output constructors, so naming one gets past name resolution cleanly. What happens next, in order: - **Name resolution succeeds** — the target is a known entry, so k6 does not treat it as a typo. - **Construction fails** — the entry's constructor has no body but an error return carrying a migration message. - **The run aborts** — no virtual user starts, no sample is produced, and nothing partial is written. The point is easy to miss: these are not names k6 forgot to delete. They are present **because** the code has to reject them by name. A user upgrading from an older k6 and re-running an old command gets a sentence telling them where their output went, instead of a bare `invalid output type` that reads like a typo. ## What each error says | `-o` name | deprecated in | removed in | what the message points you at | |---|---|---|---| | `kafka` | v0.32.0 | **v0.34.0** | an xk6 Kafka output extension | | `datadog` | v0.32.0 | **v0.34.0** | the xk6 StatsD output extension with `K6_STATSD_ENABLE_TAGS=true`, or the OpenTelemetry output | | `statsd` | v0.47.0 | **v0.55.0** | the xk6 StatsD output extension | All three replacements are **xk6 output extensions**: code that is not in the stock binary and has to be compiled into a k6 build of your own. That is the substance of the removal. The names were retired from the shipped binary and the functionality moved outside it, so the fix is never a flag — it is either a different binary or a different destination. ## The listing quirk When k6 rejects a genuinely unknown name it prints `invalid output type '<name>', available types are: <sorted list>`. That list is built by walking the constructor map and skipping exactly two entries: `kafka` and `datadog`. `statsd` is **not** skipped. So in k6 v2, `statsd` is advertised in the "available types" list yet fails the moment you select it, while `kafka` and `datadog` are hidden from the list but still recognised well enough to give you the migration message rather than a typo error. Neither name behaves the way its listing suggests, which is exactly why this makes a good interview question: you can only know it from having run it. ## Why this dates a candidate Almost every k6 tutorial, blog post and getting-started walkthrough written before these removals shows `--out influxdb` or `--out statsd` as the way to get metrics out of a run, and a great deal of that material is still the first thing a search turns up. A candidate reciting `-o statsd` as a live option is describing a k6 from before v0.55.0; a candidate reciting `-o datadog` is describing one from before v0.34.0. Neither has run the command on a current binary. ## What to use instead For a long run streaming samples to a time-series store on stock k6 v2, the built-in choices are: - **`experimental-prometheus-rw`** — pushes to any Prometheus remote-write endpoint, configured through `K6_PROMETHEUS_RW_*` variables. - **`opentelemetry`** — pushes OTLP metrics to a collector or an OTLP-capable backend, configured through `K6_OTEL_*` variables. This is the name the `datadog` error itself suggests. - **`influxdb`** — the built-in target speaks the InfluxDB v1 line protocol only; v2 needs an xk6 extension of its own. - **`json`** or **`csv`** — a local file, useful as a second destination alongside any of the above. If you genuinely need the removed protocol — an existing StatsD relay you cannot replace mid-project — the answer is a custom k6 binary built with the matching xk6 output extension, and the extension then supplies its own configuration variables. Nothing about the stock binary changes, and no flag revives the built-in. ## Recognising the failure in a pipeline The failure is loud and immediate. Because outputs are constructed before the test starts, a CI job pinned to an old k6 image and then bumped to v2 fails in the first second of the run, with the migration text in its log, rather than going green while writing nothing anywhere. Reading such a log: 1. **Find the output name in the error.** The message names the target that could not be built, and that is the only thing in the command that has to change. 2. **Read the version the message quotes.** It says which k6 release dropped the target, and therefore how far behind the pinned image had drifted. 3. **Follow the extension it points at, or repoint the run.** A custom binary keeps the protocol; switching to `opentelemetry` or `experimental-prometheus-rw` keeps the stock binary. That is why k6 constructs every output before the first virtual user starts: an output it cannot build is a configuration error, not a mode the run is allowed to continue in. The alternative — a k6 run that exits cleanly having streamed nowhere for an hour — is the failure nobody notices.
- Why keep the removed names in the binary at all instead of deleting them?So the failure explains itself. A deleted name would fall through to `invalid output type '<name>'`, which reads like a typo and sends the user hunting for a spelling mistake. Keeping the entry lets k6 answer the real question — the output moved to an xk6 extension — in the same second the command fails.
- A team must keep pushing k6 results to an existing StatsD relay. What are the options?Two. Build a custom k6 binary with the xk6 StatsD output extension, after which that extension supplies its own configuration variables; or change the destination, most simply to `opentelemetry` pointed at a collector that can forward onward. No flag or setting revives the built-in target on a stock binary.
saying these in an interview costs you the question
- Names -o statsd or -o datadog as a live k6 v2 option
- Thinks a removed output name is warned about and the run continues
- Expects the removed targets to work again behind a feature flag
- Assumes the three names were removed in the same release
- Believes the replacement extensions ship inside the stock binary