The k6/execution module provides detailed information about the current test’s execution state, including scenario metadata, VU information, and test control functions.
Map for controlling VU-level metadata. Metadata is included in every metric emitted by this VU and maintained across iterations.
Unique Identifiers: All unique identifiers are sequentially generated starting from zero (iterations) or one (VU IDs). In distributed/cloud tests, identifiers remain unique across instances, though gaps may exist due to different execution speeds.
Use iteration identifiers for data parameterization:
import { SharedArray } from 'k6/data';import exec from 'k6/execution';import http from 'k6/http';const users = new SharedArray('users', () => { return JSON.parse(open('./users.json'));});export default function () { // Each iteration gets a unique user const user = users[exec.scenario.iterationInTest % users.length]; http.post('https://test.k6.io/login', { username: user.username, password: user.password, });}
import exec from 'k6/execution';import http from 'k6/http';export default function () { // Measure time since scenario start const startTime = new Date(exec.scenario.startTime); const elapsed = new Date() - startTime; http.get('https://test.k6.io'); console.log(`Step 1: scenario ran for ${elapsed}ms`); http.get('https://test.k6.io/news.php'); const elapsed2 = new Date() - startTime; console.log(`Step 2: scenario ran for ${elapsed2}ms`);}
import exec from 'k6/execution';import http from 'k6/http';export default function () { const res = http.get('https://test.k6.io/health'); // Abort test if health check fails if (res.status !== 200) { exec.test.abort('Health check failed - aborting test'); } // Continue with test logic http.get('https://test.k6.io');}export function teardown() { console.log('Teardown still runs after test.abort()');}
import http from 'k6/http';import exec from 'k6/execution';export const options = { iterations: 10,};export default function () { http.get('https://quickpizza.grafana.com'); // Mark test as failed on iteration 3 but continue running if (exec.vu.iterationInInstance === 3) { exec.test.fail(`iteration ${exec.vu.iterationInInstance}: marked the test as failed`); } console.log(`iteration ${exec.vu.iterationInInstance} executed`);}
import http from 'k6/http';import exec from 'k6/execution';export default function () { // Set custom tags for this VU exec.vu.metrics.tags['mytag'] = 'value1'; exec.vu.metrics.tags['mytag2'] = 2; exec.vu.metrics.tags['user_type'] = __VU % 2 === 0 ? 'premium' : 'free'; // These HTTP requests will be tagged with mytag, mytag2, and user_type http.batch([ 'https://test.k6.io', 'https://quickpizza.grafana.com' ]);}
System Tag Override: Setting a tag with the same key as a system tag is allowed but requires caution. Most system tags (like url) won’t actually change their value for HTTP requests since they’re determined by the request itself. However, setting the name tag works as expected for URL grouping.
import http from 'k6/http';import exec from 'k6/execution';export default function () { // Set high-cardinality metadata (like trace IDs) exec.vu.metrics.metadata['trace_id'] = `trace-${Date.now()}-${__VU}`; exec.vu.metrics.metadata['user_id'] = `user-${exec.vu.idInTest}`; // Metrics from these requests include the metadata http.batch(['https://test.k6.io', 'https://quickpizza.grafana.com']); // Unset metadata delete exec.vu.metrics.metadata['trace_id']; // These requests won't have trace_id metadata http.batch(['https://test.k6.io', 'https://quickpizza.grafana.com']);}
Use exec.scenario.iterationInTest or exec.vu.idInTest to distribute unique data across all VUs and instances:
const user = users[exec.scenario.iterationInTest % users.length];
Avoid Overriding System Tags
Be careful when setting custom tags that match system tag names. Most won’t behave as expected:
// ❌ Won't actually change the URL tag on http.get()exec.vu.metrics.tags['url'] = 'custom';// ✅ 'name' tag works for URL groupingexec.vu.metrics.tags['name'] = 'api_call';
Use Metadata for High-Cardinality Data
Use metadata instead of tags for high-cardinality data to avoid metric explosion:
// ✅ Good: High-cardinality dataexec.vu.metrics.metadata['trace_id'] = uniqueTraceId;// ❌ Bad: Creates too many tag combinationsexec.vu.metrics.tags['trace_id'] = uniqueTraceId;
Clean Up Resources on Abort
Always use teardown() for cleanup, as it runs even after test.abort():
export function teardown(data) { // Clean up test data, close connections, etc. // This runs even if test.abort() was called}