Scenarios
Scenarios configure how VUs and iteration schedules in granular detail. With scenarios, you can model diverse workloads, or traffic patterns in load tests.
Benefits of using scenarios include:
- Easier, more flexible test organization. You can declare multiple scenarios in the same script, and each one can independently execute a different JavaScript function.
- Simulate more realistic traffic. Every scenario can use a distinct VU and iteration scheduling pattern, powered by a purpose-built executor.
- Parallel or sequential workloads. Scenarios are independent from each other and run in parallel, though they can be made to appear sequential by setting the
startTimeproperty of each carefully. - Granular results analysis. Different environment variables and metric tags can be set per scenario.
Configure scenarios
To configure scenarios, use the scenarios key in the options object.
You can give the scenario any name, as long as each scenario name in the script is unique.
The scenario name appears in the result summary, tags, and so on.
export const options = {
scenarios: {
example_scenario: {
// name of the executor to use
executor: 'shared-iterations',
// common scenario configuration
startTime: '10s',
gracefulStop: '5s',
env: { EXAMPLEVAR: 'testing' },
tags: { example_tag: 'testing' },
// executor-specific configuration
vus: 10,
iterations: 200,
maxDuration: '10s',
},
another_scenario: {
/*...*/
},
},
};Scenario executors
For each k6 scenario, the VU workload is scheduled by an executor. Executors configure how long the test runs, whether traffic stays constant or changes, and whether the workload is modeled by VUs or by arrival rate (that is, open or closed models).
Your scenario object must define the executor property with one of the predefined executor names.
Your choice of executor determines how k6 models load.
Choices include:
By number of iterations.
shared-iterationsshares iterations between VUs.per-vu-iterationshas each VU run the configured iterations.
By number of VUs.
constant-VUssends VUs at a constant number.ramping-vusramps the number of VUs according to your configured stages.
By iteration rate.
constant-arrival-ratestarts iterations at a constant rate.ramping-arrival-rateramps the iteration rate according to your configured stages.
Along with the generic scenario options, each executor object has additional options specific to its workload. For the full list, refer to Executors.
Scenario options
Scenario example
This script combines two scenarios, with sequencing:
- The
shared_iter_scenariostarts immediately. Ten VUs try to use 100 iterations as quickly as possible (some VUs may use more iterations than others). - The
per_vu_scenariostarts after 10s. In this case, ten VUs each run ten iterations.
Which scenario takes longer?
You can run to discover.
You can also add a maxDuration property to one or both scenarios.
import http from 'k6/http';
export const options = {
scenarios: {
shared_iter_scenario: {
executor: 'shared-iterations',
vus: 10,
iterations: 100,
startTime: '0s',
},
per_vu_scenario: {
executor: 'per-vu-iterations',
vus: 10,
iterations: 10,
startTime: '10s',
},
},
};
export default function () {
http.get('https://test.k6.io/');
}If you run a script with scenarios, k6 output includes high-level information about each one.
For example, if you run the preceding script, k6 run scenario-example.js,
then k6 reports the scenarios as follows:
execution: local
script: scenario-example.js
output: -
scenarios: (100.00%) 2 scenarios, 20 max VUs, 10m40s max duration (incl. grace
ful stop):
* shared_iter_scenario: 100 iterations shared among 10 VUs (maxDurati
on: 10m0s, gracefulStop: 30s)
* per_vu_scenario: 10 iterations for each of 10 VUs (maxDuration: 10m
0s, startTime: 10s, gracefulStop: 30s)The full output includes the summary metrics, like any default end-of-test summary:
/\ Grafana /‾‾/
/\ / \ |\ __ / /
/ \/ \ | |/ / / ‾‾\
/ \ | ( | (‾) |
/ __________ \ |_|\_\ \_____/
execution: local
script: scenario-example.js
output: -
scenarios: (100.00%) 2 scenarios, 20 max VUs, 10m40s max duration (incl. grace
ful stop):
* shared_iter_scenario: 100 iterations shared among 10 VUs (maxDurati
on: 10m0s, gracefulStop: 30s)
* per_vu_scenario: 10 iterations for each of 10 VUs (maxDuration: 10m
0s, startTime: 10s, gracefulStop: 30s)
█ TOTAL RESULTS
HTTP
http_req_blocked........................................................: avg=24.59ms min=1µs med=4µs max=263.64ms p(90)=22.48ms p(95)=245.04ms
http_req_connecting.....................................................: avg=11.36ms min=0s med=0s max=120.45ms p(90)=10.76ms p(95)=115.19ms
http_req_duration.......................................................: avg=115.25ms min=108.25ms med=115.66ms max=170.62ms p(90)=119.59ms p(95)=121.13ms
{ expected_response:true }............................................: avg=115.25ms min=108.25ms med=115.66ms max=170.62ms p(90)=119.59ms p(95)=121.13ms
http_req_failed.........................................................: 0.00% 0 out of 200
http_req_receiving......................................................: avg=214.61µs min=15µs med=73.5µs max=4.57ms p(90)=253.4µs p(95)=1.08ms
http_req_sending........................................................: avg=17.79µs min=3µs med=12µs max=669µs p(90)=22µs p(95)=25µs
http_req_tls_handshaking................................................: avg=12.01ms min=0s med=0s max=126.23ms p(90)=11.49ms p(95)=120.04ms
http_req_waiting........................................................: avg=115.02ms min=107.7ms med=115.33ms max=170.59ms p(90)=119.54ms p(95)=121.04ms
http_reqs...............................................................: 200 17.489795/s
EXECUTION
iteration_duration......................................................: avg=140.07ms min=108.3ms med=116.14ms max=383.32ms p(90)=187.14ms p(95)=363.64ms
iterations..............................................................: 200 17.489795/s
vus.....................................................................: 10 min=0 max=10
vus_max.................................................................: 20 min=20 max=20
NETWORK
data_received...........................................................: 2.4 MB 209 kB/s
data_sent...............................................................: 26 kB 2.3 kB/s
█ SCENARIO: per_vu_scenario
HTTP
http_req_blocked...................................: avg=23.52ms min=1µs med=4µs max=244.87ms p(90)=22.39ms p(95)=234.84ms
http_req_connecting................................: avg=11.45ms min=0s med=0s max=120.45ms p(90)=10.84ms p(95)=115.81ms
http_req_duration..................................: avg=114.86ms min=108.25ms med=115.74ms max=123.17ms p(90)=120.08ms p(95)=121.13ms
http_req_failed....................................: 0.00% 0 out of 100
http_req_receiving.................................: avg=195.59µs min=15µs med=73.5µs max=4.57ms p(90)=247.5µs p(95)=875.99µs
http_req_sending...................................: avg=20.8µs min=3µs med=12µs max=669µs p(90)=22.1µs p(95)=27.09µs
http_req_tls_handshaking...........................: avg=12.06ms min=0s med=0s max=126.23ms p(90)=11.49ms p(95)=120.61ms
http_req_waiting...................................: avg=114.64ms min=107.78ms med=115.38ms max=123.07ms p(90)=120.04ms p(95)=121.04ms
http_reqs..........................................: 100 8.744897/s
EXECUTION
iteration_duration.................................: avg=138.53ms min=108.3ms med=116.22ms max=363.71ms p(90)=144.44ms p(95)=353.48ms
iterations.........................................: 100 8.744897/s
NETWORK
data_received......................................: 1.2 MB 104 kB/s
data_sent..........................................: 13 kB 1.1 kB/s
█ SCENARIO: shared_iter_scenario
HTTP
http_req_blocked...................................: avg=25.66ms min=1µs med=4µs max=263.64ms p(90)=24.98ms p(95)=256.16ms
http_req_connecting................................: avg=11.27ms min=0s med=0s max=115.37ms p(90)=10.76ms p(95)=115.15ms
http_req_duration..................................: avg=115.65ms min=108.38ms med=115.61ms max=170.62ms p(90)=119.11ms p(95)=120.91ms
http_req_failed....................................: 0.00% 0 out of 100
http_req_receiving.................................: avg=233.63µs min=22µs med=73.5µs max=4.22ms p(90)=324.6µs p(95)=1.11ms
http_req_sending...................................: avg=14.77µs min=3µs med=12µs max=128µs p(90)=20µs p(95)=22µs
http_req_tls_handshaking...........................: avg=11.96ms min=0s med=0s max=124.34ms p(90)=11.64ms p(95)=118.98ms
http_req_waiting...................................: avg=115.4ms min=107.7ms med=115.33ms max=170.59ms p(90)=118.94ms p(95)=120.85ms
http_reqs..........................................: 100 8.744897/s
EXECUTION
iteration_duration.................................: avg=141.6ms min=108.46ms med=116.09ms max=383.32ms p(90)=189.98ms p(95)=375.24ms
iterations.........................................: 100 8.744897/s
NETWORK
data_received......................................: 1.2 MB 104 kB/s
data_sent..........................................: 13 kB 1.1 kB/s
running (00m12.8s), 00/20 VUs, 200 complete and 0 interrupted iterations
shared_iter_scenario ✓ [ 100% ] 10 VUs 00m02.7s/10m0s 100/100 shared iters
per_vu_scenario ✓ [ 100% ] 10 VUs 00m02.8s/10m0s 100/100 iters, 10 per VRun selected scenarios
Use
--scenario to run part of a multi-scenario script without editing it or adding environment-variable logic. For example, run only the workload for the API method you are developing, or run a subset on every commit and the full test less often. Selected scenarios keep their configured load.
Save this example as scenarios.js:
export const options = {
scenarios: {
api: {
executor: 'shared-iterations',
vus: 1,
iterations: 2,
exec: 'api',
},
checkout: {
executor: 'shared-iterations',
vus: 1,
iterations: 3,
exec: 'checkout',
},
},
thresholds: {
iterations: ['count>0'],
'iterations{scenario:api}': ['count>0'],
'iterations{scenario:checkout}': ['count>0'],
},
};
export function api() {
console.log('API iteration');
}
export function checkout() {
console.log('Checkout iteration');
}Select one name, or separate several names with commas:
k6 run --scenario checkout scenarios.js
k6 run --scenario api,checkout scenarios.jsThe first command runs three checkout iterations. The second runs both scenarios with their configured iteration counts. Selection preserves each scenario’s executor, load, timing, function, environment, tags, and browser settings. Other global options and the normal test lifecycle still apply, including setup() and teardown().
Names must exist in the configured scenarios object after the script’s initialization code runs. A default export alone does not define a selectable scenario; --scenario default requires an explicitly configured scenarios.default. An empty selection or an unknown name returns an error.
Load options and thresholds
You cannot combine --scenario with --vus, --duration, --iterations, or --stage. k6 ignores the corresponding top-level settings from the script, a configuration file, or environment variables and logs a warning. Settings inside selected scenarios remain intact. Execution segments remain active and can reduce the work assigned to selected scenarios.
Selection removes thresholds whose scenario tag names a configured scenario that you excluded, and logs a warning. In the example, selecting checkout skips the API threshold and keeps the global and checkout thresholds. Global thresholds, filters without a scenario tag, and filters naming a selected or unconfigured scenario remain active. A global count threshold that expects the full workload can still fail a partial run.
A skipped threshold stays skipped even if another scenario emits samples with the excluded scenario’s tag. For example, a selected checkout scenario can emit a custom metric tagged scenario:api; an API threshold removed by selection will not evaluate those samples. Refer to
thresholds for specific tags when choosing which assertions should remain shared.
Cloud runs and archives
The same selection works with k6 cloud run, including --local-execution, and k6 archive. Archives save the selected scenarios and remaining thresholds, so you can replay an archive without repeating --scenario. Omitting the flag on replay does not restore excluded scenarios or thresholds.
Run each selected scenario once
To check the selected workloads with one iteration each, combine --scenario with --once. Selection chooses which scenarios run; --once gives each one a single VU and iteration:
k6 run --scenario api,checkout --once scenarios.jsThis command runs one API iteration and one checkout iteration. Each scenario keeps its function, environment, tags, and browser settings, while --once resets its executor and timing to shared-iterations, startTime: '0s', maxDuration: '10m', and gracefulStop: '30s'. Execution segments cannot be combined with --once. Bare --once still rejects a script with multiple scenarios; explicit selection tells k6 which ones to run.

