k6 VU Calculator

How many virtual users do you need to hit your target load? Put in your numbers and get a ready-to-run k6 config.

Your workload

Peak traffic from your logs or APM, or the target you've been given.

HTTP requests one VU makes each time it runs your default function.

ms

Typical (p50) response time under load. A previous test run is the best source.

s

Total time spent in sleep() during one iteration.

Extra VUs k6 can use if responses get slower. Sets maxVUs.

You need about

260 VUs

Iterations / second
Iteration duration
Max VUs (with headroom)
VUs needed as response time changes

How the maths works

The calculator uses Little's Law, which sounds grander than it is. It says that the number of things in a system at any moment is the rate they arrive multiplied by how long each one stays:

VUs needed = iterations per second × seconds per iteration

An iteration is one run of your k6 default function. Its duration is the time spent waiting for responses plus any time spent in sleep(). So with the defaults above, 200 iterations a second that each take 1.3 seconds (300ms of response plus 1 second of think time) means about 260 VUs are busy at any given moment.

That's it. No magic, and you can do it on the back of an envelope once you've seen it a couple of times.

Which response time should I put in?

Use the response time you expect under the load you're testing at, not the response time you get clicking around on a quiet environment. If you've already run a smaller test, the median (p50) from that is a good starting point. If you have production monitoring, use the median at peak.

The number will be wrong, and that's fine. The point is to get the VU count in the right ballpark, and then let the headroom setting cover you if the system turns out to be slower than you hoped.

Open or closed model?

The chart shows why this matters. With a fixed number of VUs (a closed model), each VU waits for its response before starting the next iteration. If the system slows down, the VUs slow down with it, and your test quietly sends less traffic at exactly the moment the system is struggling.

An arrival-rate executor (an open model) keeps starting iterations at the rate you asked for, however slow the responses get. That's much closer to how real users behave on a public website: they don't wait for each other. It's why the open model config is the default above.

Closed models still have their place, for example when you're simulating a fixed pool of staff using an internal tool, or worker processes pulling jobs from a queue.

A few caveats

  • This is the steady-state number. During ramp-up, or if the system falls over, you'll see something different.
  • VUs aren't free. Each one uses memory on the machine running k6. A few thousand on one machine is usually fine for simple scripts, but check the load generator's CPU and memory during the test so it doesn't become the bottleneck.
  • Watch dropped_iterations. In an arrival-rate test, this tells you k6 couldn't start iterations on time. Either maxVUs is too low, or the system can't keep up. Both are worth knowing.

If you're reporting the results, please don't stop at the average response time. I wrote about why in Stop Reporting the Average Response Time, and there's an interactive version here.