Skip to main content
The shared-iterations executor executes a specific total number of iterations that are shared across all configured VUs. This executor is ideal when you need to ensure a specific total number of test iterations complete, regardless of how long each iteration takes.

How It Works

With shared iterations:
  1. A pool of VUs is created (specified by vus)
  2. VUs compete to execute iterations from the shared total
  3. The first VU to finish an iteration immediately grabs the next one
  4. Execution continues until all iterations complete or maxDuration is reached
  5. Faster VUs will execute more iterations than slower ones
Iteration Pool: [1][2][3][4][5][6][7][8][9][10]

VU 1: ████─────█████────███       (iterations 1, 5, 9)
VU 2: ──████████────███           (iterations 2, 3, 6)
VU 3: ────████─────████────████   (iterations 4, 7, 10)
VU 4: ──────████████              (iterations 8)

Configuration

executor
string
required
Must be shared-iterations
vus
integer
default:"1"
Number of VUs to run concurrently. Must be greater than 0.
iterations
integer
default:"1"
Total number of script iterations to execute across all VUs. Must be greater than or equal to vus.
maxDuration
duration
default:"10m"
Maximum duration for the executor. If all iterations don’t complete within this time, the executor stops and remaining iterations are dropped.

Example

Basic Configuration

import http from 'k6/http';
import { sleep } from 'k6';

export const options = {
  scenarios: {
    shared_iter_scenario: {
      executor: 'shared-iterations',
      vus: 10,
      iterations: 100,
      maxDuration: '30s',
    },
  },
};

export default function () {
  http.get('https://test.k6.io');
  sleep(1);
}
This runs 100 total iterations shared among 10 VUs, with a maximum duration of 30 seconds.

Data-Driven Testing

import http from 'k6/http';
import { SharedArray } from 'k6/data';

const testData = new SharedArray('users', function () {
  return JSON.parse(open('./users.json'));
});

export const options = {
  scenarios: {
    data_driven: {
      executor: 'shared-iterations',
      vus: 5,
      iterations: testData.length, // One iteration per data row
      maxDuration: '5m',
    },
  },
};

let iterationCounter = 0;

export default function () {
  const user = testData[iterationCounter++];
  http.post('https://test.k6.io/login', JSON.stringify(user));
}

When to Use

Use the shared iterations executor when:
  • You need to process a specific amount of test data exactly once
  • You want to ensure a fixed total number of operations complete
  • You need to iterate through a dataset with each iteration processing one item
  • The total work is more important than the execution time
  • You want faster VUs to do more work

Behavior Details

VU Distribution

Iterations are not evenly distributed. VUs that complete iterations faster will execute more iterations:
// If VU 1 is consistently faster:
// VU 1 might do: iterations 1, 3, 5, 7, 9, 11, 13...
// VU 2 might do: iterations 2, 6, 10, 14...
// VU 3 might do: iterations 4, 8, 12...

Maximum Duration

If iterations don’t complete within maxDuration, execution stops and the remaining iterations are recorded as dropped:
export const options = {
  scenarios: {
    example: {
      executor: 'shared-iterations',
      vus: 2,
      iterations: 1000,
      maxDuration: '10s', // Might not complete all 1000
    },
  },
};
Dropped iterations are tracked in the dropped_iterations metric.

Minimum Iterations

The number of iterations must be at least equal to the number of VUs. This ensures each VU can execute at least one iteration:
// ❌ Invalid - iterations < vus
{
  executor: 'shared-iterations',
  vus: 10,
  iterations: 5, // Error!
}

// ✓ Valid
{
  executor: 'shared-iterations',
  vus: 10,
  iterations: 10, // OK
}

Metrics

The executor emits these specific metrics:
  • iterations - Total completed iterations
  • iteration_duration - Time to complete each iteration
  • dropped_iterations - Iterations that didn’t complete within maxDuration
  • vus - Number of active VUs
  • vus_max - Maximum number of VUs

Common Patterns

Processing a Queue

import http from 'k6/http';

const tasks = new SharedArray('tasks', () => 
  Array.from({ length: 500 }, (_, i) => ({ id: i }))
);

let taskIndex = 0;

export const options = {
  scenarios: {
    process_queue: {
      executor: 'shared-iterations',
      vus: 20,
      iterations: tasks.length,
    },
  },
};

export default function () {
  const task = tasks[taskIndex++];
  http.post('https://api.example.com/process', JSON.stringify(task));
}

Smoke Test with Exact Count

export const options = {
  scenarios: {
    smoke: {
      executor: 'shared-iterations',
      vus: 1,
      iterations: 10, // Exactly 10 iterations
      maxDuration: '1m',
    },
  },
};

Comparison with Per VU Iterations

FeatureShared IterationsPer VU Iterations
Total iterationsFixedvus × iterations
DistributionDynamic (faster VUs do more)Even (each VU does same amount)
PredictabilityLess predictable per-VUMore predictable per-VU
Use caseProcess fixed datasetConsistent per-user load

Best Practices

  1. Set appropriate maxDuration: Ensure maxDuration is long enough for all iterations to complete
  2. Monitor dropped iterations: Check the dropped_iterations metric to ensure work completes
  3. Use SharedArray for data: When processing datasets, use SharedArray to avoid memory duplication
  4. Consider execution segment: For distributed testing, iterations are split across k6 instances

See Also

Build docs developers (and LLMs) love