> OctoPerf load testing - K6 limits documentation page. What a K6 Virtual User does differently from a JMeter one, and what OctoPerf does not support for K6.

Source: https://api.octoperf.com/doc/design/edit-virtual-user/action-types/k6-actions/k6-limits/

# K6 limits

A [K6 Virtual User](https://api.octoperf.com/doc/design/create-virtual-user/import-k6-scripts/) runs the scripts as they are, on the K6 of the `octoperf/k6` image. Most of what OctoPerf offers applies to it; this page lists what does not, or what works differently than with JMeter.

## Load

- **The scenario sets the load.** The `scenarios`, `vus`, `duration`, `iterations` and `stages` of the script `options` are ignored at run time: the [user profile](https://api.octoperf.com/doc/runtime/edit-scenario/edit-user-profile/options/k6/) decides how many virtual users run, and for how long. [Import Scenario](https://api.octoperf.com/doc/design/create-virtual-user/import-k6-scripts/#import-the-scenario) converts the script scenarios into an OctoPerf scenario.
- **No open model.** The `constant-arrival-rate` and `ramping-arrival-rate` executors, which start iterations at a given rate whatever the number of virtual users, have no OctoPerf counterpart: they are never converted, and a scenario runs a set number of virtual users.
- **Thresholds do not stop the test.** The `abortOnFail` of a threshold is ignored unless the user profile turns on [Abort on failed threshold](https://api.octoperf.com/doc/runtime/edit-scenario/edit-user-profile/options/k6/#script). Even then, it only stops K6 on the load generator where the threshold failed, like the **Stop Test** error policy of JMeter.

## Script

- **Only the extensions of the load generators.** A script can import the modules of K6 and the [extensions](https://api.octoperf.com/doc/design/edit-virtual-user/action-types/k6-actions/k6-protocols/#extensions) of the `octoperf/k6` image, not an xk6 extension downloaded when the test starts.
- **No browser testing.** The `k6/browser` module is not supported: to load test a web page in a real browser, use a [Playwright Virtual User](https://api.octoperf.com/doc/design/create-virtual-user/import-playwright-node-project/) instead.
- **No Counter variables.** Use `__VU` and `__ITER` instead of a counter: see [K6 variables and data](https://api.octoperf.com/doc/design/edit-virtual-user/action-types/k6-actions/k6-variables/).
- **No npm packages.** Only relative imports, between the files of the Virtual User, and `https://` imports resolve: K6 does not run `npm install` nor a bundler.

## Test

- **No APM integration.** The [APM](https://api.octoperf.com/doc/runtime/edit-scenario/integrations-automation/apm/) settings of a scenario only apply to JMeter virtual users. In a scenario that only runs K6 virtual users, the **Live Reporting** and **APM** panels are disabled.
- **Error details are capped.** In a standard test, a failed request keeps its request and its response in the report for its first 3 occurrences per request and response code, and 1000 occurrences per load generator in all, the same limits as JMeter. A [validation](https://api.octoperf.com/doc/design/edit-virtual-user/validation/) keeps every exchange.
- **Custom metrics are capped.** Each load generator reports at most 100 custom metric names. A script minting a new name per request, from an id or a URL, stops adding metrics past that limit, and the load generator log says so.

## Report

- **One node per script.** The report tree holds the entrypoint of the K6 Virtual User, its `group` blocks and its requests: a module the entrypoint imports is a file, not a node of its own, and its requests and errors are filed under the entrypoint.
- **Iterations, not users.** K6 counts iterations, not virtual users that start and stop: the started and finished users of the report are the iterations of K6.
- **Checks are not requests.** A failed `check()` counts as a failed assertion, never as a request error.
