Q9 of 38 · Performance

How do you parametrise test data in k6?

PerformanceMidperformancek6test-datashared-arrayparametrisation

Short answer

Short answer: Load CSV or JSON via SharedArray for memory efficiency across VUs, pick rows by VU/iteration index for uniqueness, pull secrets from environment variables with __ENV, and avoid loading large files inside the default function — that runs per iteration.

Detail

k6 has a few specific patterns for getting data into a test without blowing up memory or hitting external services unnecessarily.

SharedArray — the right primitive for bulk test data. The callback runs once during init, the result is held in a single read-only memory slab, and all VUs in the instance share the same copy. Without this, each VU duplicates the dataset — 100 VUs × 50MB = 5GB of RAM for nothing.

Picking rows uniquely. __VU (VU number) and __ITER (iteration index within a VU) are k6 globals. Common patterns: users[__VU % users.length] for one-user-per-VU, users[(__VU * 1000 + __ITER) % users.length] for unique-per-iteration. For datasets larger than VU count, use __ITER to walk through unread rows.

Secrets and environment values__ENV.API_KEY reads from process env at script start. Pass with -e API_KEY=xxx or set in the runner's environment. Never inline secrets in the script.

Anti-pattern: open() or JSON.parse(open()) inside the default function — it runs every iteration, hammers disk, and explodes memory. open() only works in init, hence the SharedArray wrapping.

Generating data on the fly: for cases where you need millions of unique values (UUIDs, random strings), generate per-iteration with crypto.randomUUID() or k6's uuidv4 — much cheaper than maintaining a giant static dataset.

// EXAMPLE

k6-shared-array.js

import { SharedArray } from 'k6/data';
import http from 'k6/http';
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';

const users = new SharedArray('users', () => {
  const csv = open('./users.csv');
  return papaparse.parse(csv, { header: true }).data;
});

export const options = { vus: 100, duration: '5m' };

export default function () {
  const u = users[(__VU - 1 + __ITER) % users.length];
  http.post(__ENV.BASE_URL + '/login', {
    email: u.email,
    password: __ENV.TEST_PASSWORD,
  });
}

// WHAT INTERVIEWERS LOOK FOR

Knowing SharedArray (signal of beyond-toy k6 use), avoiding open() in the iteration loop, and pulling secrets from __ENV. Bonus for mentioning data uniqueness via __VU/__ITER.

// COMMON PITFALL

Calling open() and JSON.parse() in the default export — fine for 10 VUs, OOMs at 1000.