What does k6 require of the two arguments to new SharedArray(name, fn), and of where it is called?
answer
- name, function, init context
- the second argument cannot be async
- the loader must return an array
- a repeated name reuses the built array
basics
~20 sk6 requires a non-empty name, a non-async function as the second argument that returns an array, and the call itself to sit in the init context. Each violation throws during init, before any VU iterates.
solid answer
~40 sThe name is the identity, because VUs are separate JavaScript runtimes and k6 keeps one process-wide map from name to data — so a second `new SharedArray('users', ...)` with a name already loaded returns the existing array and **never calls its own loader**. An empty name throws `empty name provided to SharedArray's constructor`. The second argument must be a function (`a function is expected as the second argument of SharedArray's constructor`) that is not `async` (`SharedArray constructor does not support async functions as second argument`) and returns an array (`only arrays can be made into SharedArray`). Constructing one outside init throws `new SharedArray must be called in the init context`.
code
javascript · 15 linesimport { SharedArray } from 'k6/data';
const first = new SharedArray('users', function () {
console.log('loader ran');
return [{ id: 1 }, { id: 2 }];
});
// Same name: k6 returns the array built above and never calls this loader.
const second = new SharedArray('users', function () {
throw new Error('never reached');
});
export default function () {
console.log(first.length, second.length); // 2 2
}go deeper
Learn the shape by heart: new SharedArray('name', function () { return rows; }), written at the top level of the script file and never inside the default function.
Be able to name the failure for each broken rule: empty name, non-function, async function, a loader returning a non-array, and construction outside the init context. All of them throw during init.
Watch for the silent case in review. A name reused across two data files means the second loader never runs, and no error ever appears to tell you which rows the test is really using.
Treat SharedArray names as a namespace shared by a script and everything it imports. Agree a naming convention early, because k6 will not warn you when two modules collide on one.
## The four things k6 checks `new SharedArray(name, fn)` is validated eagerly, while the init context runs and before a single iteration starts. k6 checks, in order: that it is being called in the init context; that `name` is not the empty string; that the second argument is not an `async` function; and that the second argument is a function at all. It then calls that function and checks that what came back is an array. Every one of those failures is thrown, not warned about, so a broken constructor stops the run at startup rather than during traffic. ## Why the name, not the variable, is the identity Every VU is its own JavaScript runtime, and each of them executes the init code. The `const users = ...` binding therefore exists once per VU and cannot be the thing that identifies the shared data. k6 instead keeps a **single, process-wide map from name to stored data**, and the constructor is a load-or-store against that map: - The first call for a given name runs the loader and stores the result. - Every later call for the same name — from another VU, or from a second line in the same script — returns the stored data and **does not invoke its own loader function**. - Two different names give two independent data sets, each loaded once. That last behaviour is the one that bites in review. A reused name across two modules means the second loader is dead code, silently, with no warning: your script believes it is testing with one file's rows while it is actually holding another's. ## The loader function's contract The second argument must be a **plain, synchronous function that returns an array**. `async` is rejected explicitly by name, and a non-`async` function that happens to return a promise fails the array check instead — a promise is not an array. The reason is the same in both cases: the constructor has to produce the finished, indexable data before it returns, and it has nothing sensible to do with a pending value. The array requirement is equally concrete. k6 walks the returned value by integer index and stores `JSON.stringify()` of each element, so it needs something whose class really is `Array`. A loader that returns an object, a string or a number fails with `only arrays can be made into SharedArray`. The check is on the value's class, not on how array-like it looks, so an object with numeric keys and a `length` property is rejected just as firmly as a string is. ## Why the init context is mandatory k6 decides whether it is in the init context by asking whether the current VU has run **state** — the per-VU machinery (cookie jar, tags, metric samples) that only exists once a VU begins executing iterations. During init there is no such state, so the constructor is allowed. Inside `setup()`, the default function or `teardown()` the state exists and the constructor throws. The practical consequence is the one k6's documentation spells out: a `SharedArray` can be populated only from data you have at the very start of the test, never from something you received in a response. ## Reading the failure messages | what you wrote | what k6 does | |---|---| | `new SharedArray('', fn)` | throws `empty name provided to SharedArray's constructor` | | `new SharedArray('users', 'astring')` | throws `a function is expected as the second argument of SharedArray's constructor` | | `new SharedArray('users', async () => rows)` | throws `SharedArray constructor does not support async functions as second argument` | | loader returns `{ a: 1 }` | throws `only arrays can be made into SharedArray` | | constructed inside `setup()` or the default function | throws `new SharedArray must be called in the init context` | | `new SharedArray('users', fn)` a second time | returns the array the first call built; `fn` is never invoked | ## What k6 does not check Two things pass silently and are worth knowing about: 1. **A duplicate name is not an error.** It is the designed behaviour, so nothing tells you a loader was skipped. 2. **The contents of the array are not validated.** k6 serialises each element with `JSON.stringify()`, so anything JSON cannot express — a method on a row, a property set to `undefined` — simply disappears without a diagnostic. 3. **Nothing checks that the loader is cheap.** It runs during init, inside the startup window, so an expensive loader delays the moment the run begins rather than showing up later as slow iterations.
- In k6, why can a SharedArray loader not be an async function?The constructor must produce the finished, indexable data synchronously while the init context runs. An `async` function returns a promise instead, so k6 rejects it up front with `SharedArray constructor does not support async functions as second argument` rather than storing something it cannot walk by index.
- What happens in k6 if two modules construct SharedArrays with the same name but different loaders?Whichever construction runs first wins. k6 keys its one process-wide store by name, so the second call returns the already-built data and silently ignores its own loader. That makes a reused name a real hazard when the two loaders read different files.
saying these in an interview costs you the question
- Thinks the SharedArray name is only a label for the output
- Passes an async loader and expects k6 to await it
- Expects a duplicate SharedArray name to raise an error
- Builds the SharedArray inside setup() instead of init
- Returns an object from the loader and expects k6 to wrap it