k6 v2.0.0-rc1 is here 🎉!
This release marks the first release candidate for k6 v2.0.0 — a major version that completes a long-running cleanup of deprecated APIs, old commands, and obsolete configuration options. Like the v1.0.0-rc1 before it, the purpose of this release is to give the community a chance to test the upgrade path, identify any issues, and migrate scripts or workflows affected by breaking changes. If you encounter any problems, please report them.
Here’s a glimpse of what’s changed in this release:
- The Go module path has changed to
go.k6.io/k6/v2— all extensions must update their import paths to be compatible with v2. - Removal of all long-deprecated CLI commands and flags:
k6 login,k6 pause,k6 resume,k6 scale,k6 status,--no-summary,--upload-only, and more. - The
externally-controlledexecutor has been removed — scripts usingexecutor: externally-controlledwill no longer run. - Cloud run non-threshold aborts (aborted by user, system, timeout, etc.) now return exit code
97instead of0. options.ext.loadimpactis no longer supported — useoptions.cloud.k6/experimental/redismodule has been removed.- The
k6 cloudcommand now shows help by default instead of attempting to run. - A stack is now required for all
k6 cloudcommands — the previous fallback to the first available stack has been removed. - The web-vitals library has been updated to v5.1.0, removing the deprecated FID metric.
Breaking changes
These are changes that require you to update your scripts, CI/CD pipelines, or configuration files before upgrading.
Go module path changed to go.k6.io/k6/v2 #5777
Following the Go module versioning conventions, the k6 module path has changed from go.k6.io/k6 to go.k6.io/k6/v2.
Any extension or external package that imports go.k6.io/k6 must update all import paths to go.k6.io/k6/v2. For the vast majority of extensions this is the only change needed — a mechanical find-and-replace across the codebase:
go.k6.io/k6/ → go.k6.io/k6/v2/For example:
// Before
import "go.k6.io/k6/js/modules"
// After
import "go.k6.io/k6/v2/js/modules"As a result, no existing extensions will be compatible with v2.0.0-rc1. As we move toward the final v2.0.0 release, we expect most extensions to either already support the new path or to do so shortly after.
Removed CLI commands #5653
The following commands for controlling a running test have been removed. They have not been functional for most use cases since the REST API they relied on was limited to specific execution modes:
k6 pausek6 resumek6 scalek6 status
Migration: There is no replacement. These commands relied on the externally-controlled executor, which has also been removed in v2.0.0 (see below).
Removed externally-controlled executor #5846
The externally-controlled executor has been removed. It was legacy code from an older k6 Cloud architecture that allowed external systems to scale VUs and pause/resume a running test via the k6 REST API — the capability that k6 pause, k6 resume, k6 scale, and k6 status relied on.
Migration: There is no replacement. Any test script with executor: externally-controlled will fail to start. Migrate to a different executor based on the desired load profile (e.g., ramping-vus, constant-vus, constant-arrival-rate).
Removed k6 login command #5134
The top-level k6 login command and its subcommands (k6 login cloud, k6 login influxdb) have been removed.
Migration:
- Replace
k6 login cloud→k6 cloud login - InfluxDB authentication is no longer configurable via a login command. Use environment variables such as
K6_INFLUXDB_*to configure the InfluxDB output directly.
k6 cloud script.js no longer runs a test #5624
Running k6 cloud without an explicit subcommand (i.e., the old positional-argument form k6 cloud script.js) now shows the help output instead of attempting to run the test. The run subcommand was already the recommended path since k6 cloud run was introduced.
Migration: Replace k6 cloud script.js with k6 cloud run script.js.
Removed --upload-only flag #5844
The --upload-only flag on the k6 cloud command has been removed.
Migration: Use k6 cloud upload script.js to upload a test without running it.
Removed --no-summary flag #5729
The --no-summary flag has been removed.
Migration: Replace --no-summary with --summary-mode=disabled.
Removed --summary-mode=legacy #5730
The legacy value for --summary-mode has been removed.
Migration: There is no direct equivalent — the new summary format is different from the legacy one. Review the available summary modes and choose the one that best fits your needs: compact (the default) or full for more detailed output.
Removed options.ext.loadimpact support #5774
The options.ext.loadimpact configuration block in test scripts is no longer supported.
Migration: Move all cloud-related configuration from options.ext.loadimpact to options.cloud:
// Before
export const options = {
ext: {
loadimpact: {
projectID: 12345,
name: "My Test",
},
},
};
// After
export const options = {
cloud: {
projectID: 12345,
name: "My Test",
},
};Removed k6/experimental/redis module #5485
The k6/experimental/redis module has been removed from the k6 core binary. It was shipped as an experiment and has not been promoted to stable.
Migration: Change your import from k6/experimental/redis to k6/x/redis. With auto-extension-resolution, k6 will automatically provision the xk6-redis extension when it sees the k6/x/redis import.
Removed ExporterType option from OpenTelemetry output #5754
The deprecated exporterType configuration option for the OpenTelemetry output has been removed.
Migration: Replace K6_OTEL_EXPORTER_TYPE with K6_OTEL_EXPORTER_PROTOCOL. The accepted values are grpc and http/protobuf.
Removed SingleCounterForRate option from OpenTelemetry output #5830
The temporary SingleCounterForRate escape-hatch option for the OpenTelemetry output has been removed. It was introduced as a one-release migration aid in #5164 to let users revert to the old pair-of-counters format (<metric>.occurred + <metric>.total) while upgrading. Rate metrics are now always exported as a single counter with a condition attribute (nonzero/zero).
Migration: Remove any K6_OTEL_SINGLE_COUNTER_FOR_RATE=true configuration. If you were using the old pair-of-counters format, update your dashboards and queries to use the single counter with condition attribute instead.
Removed K6_BINARY_PROVISIONING environment variable #5734
The K6_BINARY_PROVISIONING environment variable, deprecated in v1.2.0, has been removed.
Migration: Remove K6_BINARY_PROVISIONING from your environment. Auto-extension-resolution is enabled by default; K6_AUTO_EXTENSION_RESOLUTION only needs to be set explicitly if you want to disable it.
Removed K6_ENABLE_COMMUNITY_EXTENSIONS environment variable #5733
The K6_ENABLE_COMMUNITY_EXTENSIONS environment variable has been removed. The community and cloud extension catalogs were merged server-side, making this flag a no-op since the catalogs were unified.
Migration: Remove K6_ENABLE_COMMUNITY_EXTENSIONS from your environment. Community extensions are now resolved through the default build service URL automatically.
Stack is now required for all k6 cloud commands #5833
Providing a stack is now mandatory for all k6 cloud commands (k6 cloud run, k6 cloud upload, k6 cloud run --local-execution). Previously, omitting a stack would fall back to the first available stack with a deprecation warning — that fallback has been removed. Likewise, k6 cloud login now requires both a token and a stack; passing one without the other fails with an explicit error.
Migration: Ensure a stack is always provided via k6 cloud login --stack passing the stack slug or the full URL. Alternatively, the K6_CLOUD_STACK_ID environment variable, or the stackID script option are available to be set before running any k6 cloud command .
Removed legacy configuration file path migration #5609
k6 no longer automatically migrates configuration files from the old {USER_CONFIG_DIR}/loadimpact/config.json path introduced before k6 v1.0.0.
Migration: If you still have a config file at the old path, move it to {USER_CONFIG_DIR}/k6/config.json. You can also re-run k6 cloud login to regenerate the file at the correct location.
Cloud run non-threshold aborts now exit with code 97 #5769
Previously, most cloud abort scenarios returned an exit code of 0, making it impossible for CI pipelines to distinguish a failed run from a successful one. These scenarios now return exit code 97.
Migration: Review any CI pipeline logic that treats exit code 0 as success for cloud runs. Cloud runs that abort for reasons other than threshold violations will now return exit code 97.
Browser: FID metric removed, web vitals updated to v5.1.0 #5661
The browser_web_vital_fid metric has been removed. FID (First Input Delay) was deprecated as a Core Web Vital and replaced by INP (Interaction to Next Paint). The embedded web-vitals library has been updated from v3 to v5.1.0, which reflects this change.
Migration: Update any dashboards, alerts, or threshold rules that reference browser_web_vital_fid to use browser_web_vital_inp instead.
New features
Cloud secret source #5738
A new built-in secret source, cloud, allows k6 scripts to retrieve secrets stored in Grafana Cloud directly during local execution. Pass --secret-source=cloud when running k6 cloud run --local-execution to make cloud-managed secrets available to your script via secrets.get(). Thanks, @vortegatorres!
k6 cloud run --local-execution --secret-source=cloud script.jsExtension tab-completion provisioning #5761
When using shell tab-completion, pressing TAB after a fully-typed extension name (e.g. k6 x docs <TAB>) will now automatically provision a custom binary with that extension and delegate the completion request to it. This means extension-specific flags and subcommands are available via tab-completion without any manual setup.
Pre-manifest extension dependencies captured in archive metadata #5819
When creating a k6 archive (k6 archive), extension dependency information is now captured in metadata.json under a "dependencies" field, using the constraints declared by the script before any external manifest overrides are applied. This ensures that k6/x/ imports are preserved correctly during auto-extension-resolution re-execution.
UX improvements and enhancements
- #5815 Warns when
http.get()orhttp.head()receive extra arguments that are silently ignored, helping catch common scripting mistakes. Thanks, @moko-poi! - #5657 Adds automatic retries to
newAction-based Locator APIs in the browser module, improving reliability of browser tests. Thanks, @janHildebrandt98! - #5779 Adds a
k6 x docshint to the main k6 help output for built-in documentation discovery. Thanks, @Reranko05! - #5788 Adds a
k6 x explorehint to the main k6 help output for extension discovery.
Bug fixes
- #5855 Fixes auto-extension-resolution incorrectly triggering binary provisioning when a script manifest specifies a dependency as a Go module pseudo-version (
v0.0.0+shaorv0.0.0-timestamp-sha), even when the running binary already satisfied the constraint. - #5769 Fixes several
k6 cloud runTUI issues: ghost duplicate progress bars appearing after the run finishes, a timer that stalled and then jumped to 100%, and a stale timer racing with the status line. - #5814 Fixes
k6 cloud run --local-executionignoringK6_CLOUD_PUSH_REF_IDand unconditionally creating a new test run instead of reusing the provided run ID. Thanks, @Reranko05! - #5716 Fixes WebSocket
bufferedAmountnot being incremented when sending TypedArrays, causing it to go negative. Thanks, @prakharbirla-ng! - #5630 Fixes duplicate redirect request metric emissions in the browser module, where each redirect was incorrectly emitting metrics for all prior redirects in the chain.
- #5786 Fixes swapped Min and Max values for Gauge metrics in Cloud output v2, which caused incorrect peak and floor values in cloud test result queries. Thanks, @esquonk!
- #5785 Fixes a race condition in the browser module’s
handleExitEventwhereDone()was signalled before the subscription was removed, causing tests to hang until the timeout. - #5574 Fixes position parser for base pointer options. Thanks, @chrismooreproductions!
Maintenance and internal improvements
- #5847 Moves
TaskQueuefrom the externalgithub.com/mstoykov/k6-taskqueue-libintointernal/js/taskqueue, eliminating an awkward reverse dependency where the library’s own tests depended on k6. - #5775 Moves xk6-dashboard source code into
internal/dashboard, making the web dashboard a built-in part of the k6 binary without requiring a separate extension. The dashboard is available viak6 run --out=web-dashboard. - #5703, #5818 Uses Go’s
synctestpackage withinlib/executor, eventloop, and timer tests for virtualized time, improving test determinism. - #5778 Bumps Ubuntu CI runners to 24.04 and always installs Chromium for browser tests.
- #5826, #5827 Updates
go.opentelemetry.io/otel/exporters/otlp/otlptracehttpandotlpmetrichttptov1.43.0[security], adding a 4 MiB response body cap to mitigate memory exhaustion from misconfigured or malicious servers. - #5669 Updates
go.opentelemetry.io/otelpackages. - #5740, #5796 Updates
github.com/grafana/sobekdigest. - #5783, #5838, #5862 Updates
github.com/grafana/k6-cloud-openapi-client-go. - #5407, #5801 Updates
github.com/mailru/easyjsontov0.9.2. - #5616, #5805 Updates
github.com/evanw/esbuildtov0.28.0. - #5667 Updates golangci-lint.
- #5799 Updates
buf.build/gen/go/prometheusprotobuf. - #5800 Updates
github.com/andybalholm/brotlitov1.2.1. - #5804 Updates
examples/dependencies. - #5806 Updates
github.com/fatih/colortov1.19.0. - #5807 Updates
github.com/puerkitobio/goquerytov1.12.0. - #5840 Updates
github.com/mattn/go-isattytov0.0.21. - #5857 Updates Go to
v1.25.9. - #5863, #5880 Updates
github.com/grafana/k6providertov0.4.0. - #5670 Updates GitHub artifact actions (major).
- #5693 Updates
crazy-max/ghaction-chocolateytov4. - #5706 Updates
actions/setup-goto4a36011. - #5707 Updates
anchore/sbom-actiontov0.24.0. - #5718, #5861 Updates
github/codeql-actiontov4.35.2. - #5720, #5802 Updates
docker/login-actiontov4.1.0. - #5771, #5798 Updates
grafana/shared-workflowsactions. - #5836 Updates
actions/upload-artifact. - #5809, #5839 Updates the Docker base image tags (Debian to v13, Go to
v1.26.2). - #5872 Fixes v6 cloud client losing the request body when retrying after a
Connection: closeresponse. - #5871 Returns an accurate error from the v6 cloud client when a test name lookup returns no results.
- #5751 Updates
github.com/klauspost/compresstov1.18.5. - #5841 Updates
golang.org/xpackages. - #5860 Updates Alpine Docker image to
v3.23.4.
External contributors
A huge thank you to the external contributors who helped during this release: @moko-poi, @janHildebrandt98, @Reranko05, @prakharbirla-ng, and @chrismooreproductions! 🙏

