Skip to content

Support custom k6 binaries with xk6 extensions (SSE, gRPC streaming, custom outputs, etc.) #316

Description

@moko-poi

Summary

The Distributed Load Testing on AWS solution currently ships and executes only the standard, vanilla k6 binary bundled inside the Taurus container. This blocks a substantial portion of real-world k6 use cases that depend on xk6 extensions, and effectively limits the solution's "k6 support" to a subset of what the k6 ecosystem actually covers.

We would like an officially supported path to run k6 test scripts that require xk6 extensions on DLT.

Background — extensions are first-class in the k6 ecosystem

Per the official k6 documentation:

"The k6 extension ecosystem enables developers and testers to extend k6 to cover use cases not supported natively in the core."
grafana/docs/k6/latest/extensions

k6 officially recognizes four extension categories:

  • JavaScript extensions — extend the JS API used in test scripts (gRPC streaming, SSE, Kafka, MQTT, Redis, SQL DBs, custom protocols, etc.)
  • Output extensions — emit metrics in custom formats / to custom destinations
  • Secret Source extensions
  • Subcommand extensions

The xk6 README describes itself as the "k6 extension development toolbox" (github.com/grafana/xk6). Extensions are written in Go and must be compiled into k6 at build time; they cannot be loaded dynamically at runtime. The canonical build flow is:

docker run --rm -it -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" \
  grafana/xk6 build v1.0.0 --with github.com/<owner>/<extension>

This compile-time requirement means a script importing, for example, k6/x/sse from xk6-sse cannot be executed by a stock k6 binary at all — it fails at module resolution before any test run begins.

The problem

Because DLT ships only the stock k6 binary inside the Taurus container, any script that depends on an xk6 extension cannot run on DLT. Concrete examples of impacted use cases:

Use case Required extension(s)
Server-Sent Events (SSE) streaming endpoints xk6-sse
Modern gRPC streaming patterns xk6-grpc (some flows)
Kafka producer/consumer load xk6-kafka
MQTT / IoT broker load xk6-mqtt
SQL-backed scenarios (data correlation against DBs) xk6-sql
Browser-driven tests via custom drivers various
Custom output to internal telemetry systems various output extensions

These are not edge cases — many of them appear in the official k6 extension catalog and are part of how teams actually use k6 in production.

Why this matters for the "k6 support" claim

The DLT README lists k6 alongside JMeter and Locust as a supported framework. However, given that extensions are explicitly positioned by the k6 maintainers as the mechanism for "covering use cases not supported natively in the core," users with non-trivial scenarios face one of the following:

  1. Maintain a fork of DLT just to ship a custom k6 image (high ongoing cost)
  2. Move off DLT entirely (e.g., to k6 Operator on Kubernetes or Grafana Cloud k6) for any extension-dependent scenario, fragmenting the load test infrastructure
  3. Rewrite scenarios to avoid extensions, sometimes losing protocol fidelity

None of these options preserves the value of having an integrated AWS-native distributed load testing solution.

Proposed solutions (any of these would help)

Listed in roughly increasing implementation effort:

  1. Allow specifying a custom k6 container image in the test configuration (similar to how custom Docker images can be specified for other frameworks). Users would build their own k6 image with xk6 build --with ... and reference it.
  2. Provide an opt-in build step that, given a list of --with flags in the test config, builds a custom k6 binary inside the Taurus container before test execution.
  3. Document a supported fork pattern that shows exactly which CFN/CDK pieces to override to swap in a custom k6 image without diverging from the rest of the solution.
  4. Ship a curated set of common extensions in the default DLT k6 image (at least the official xk6-grpc, plus widely-used community ones like xk6-sse, xk6-kafka, xk6-sql).

Option 1 or 3 alone would unblock most users, since the build/maintenance of the custom image would stay on the user side.

Related

Environment

  • DLT version: v4.1.0 (latest at time of writing)
  • Use case driving this request: SSE-based load tests for a copilot streaming endpoint (xk6-sse required)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions