This article takes a look at the k6 pause/resume/scale/stats/status commands, and how to use them to control and query a remote k6 instance running a test. This can be useful when you want to dynamically control a load test at runtime, pausing it or modifying the number of virtual users.
Most people using k6 are only familiar with the most straightforward use case, where you issue a command like k6 run myscript.js and then lean back while the test is running, waiting for your results to come out. The most common case is probably to run with a fixed number of virtual users (VUs) for the whole duration of the test, but there is also the option of defining "stages” that ramp the load level up and down during the test.
Regardless though, the test will run its predefined course - there is no way for you to change how it ramps the load up or down, short of killing the k6 process and starting over.
There are, however, ways to control a live, running k6 test, or to query it for information. This can be very useful if you’re e.g. doing exploratory testing where you have no idea how many virtual users your system can handle, and want some freedom to scale up or down the load dynamically depending on how the target system is doing.
The built-in k6 commands "pause”, "resume”, "scale”, "stats” and "status” can be used to control the behaviour of a running test. Basically, what you do is start a k6 test in one terminal window and then from another terminal window (or of course it could be programmatic execution - a batch job or whatnot) you issue k6 commands to control the running test. Here are some examples:
Starting k6 in one window, then using k6 from other window to query the running test
k6 pause / resume
Starting k6 in one window, then pausing the test from the second window
It is often useful to start a test in paused mode:
Starting k6 in paused mode
And then use k6 resume to resume it:
Resuming the test from the second window
This command allows you to scale the load level (in terms of virtual users, VUs) up or down during the test.
Scaling up from 1 VU to 10 VUs and then down to 5 VUs
Note that there are two VU parameters: vus and vus-max. The first one is the actual number of currently active VUs in the test. It is the one you use to ramp up and down the load level. The second value (vus-max) is the current limit for how many vus you can activate. This is what happens if you try and scale vus to a level that is above vus-max:
Trying to scale vus to a value higher than vus-max
The reason for having the vus-max parameter is that creating new VUs is an expensive operation - a lot of memory has to be reserved and a lot of data structures have to be initialized. Initializing a lot of new VUs at runtime can negatively impact a load test, meaning that the test more or less halts for a while, or it can affect measurement reliability.
If it was too simple to change the VU level arbitrarily at runtime, users might unknowingly get into trouble when starting a load test with a low VU number and then using e.g. k6 scale to greatly increase the number of VUs instantaneously.
So k6’s way of trying to both make users continuously aware of this issue, and still provide flexibility, is to have the vus-max parameter that you need to set before you set the vus parameter. It also gives users more control; Increasing vus-max means that k6 will immediately start allocating memory etc for the extra VUs. This means that the user can decide when k6 should waste CPU resources on allocation and setup tasks and when it should use CPU to actually generate load test traffic and taking accurate measurements.
Below is an example where we increase vus-max from 10 to 50 VU during a test (not recommended, but at these low levels of traffic there is no noticeable freeze)
Changing vus-max at runtime - be careful and read the next section before doing this
- The best thing is to set vus-max once, on startup, and set it high enough that you will not need to increase it at runtime.
- The second best thing, if you do need to increase vus-max at runtime, is to pause the test, increase vus-max, and then resume again. That way, nothing important happens while k6 is busy creating new VUs.
If you want to be a cowboy you can also do what we did in the screenshot above and just change vus-max while the test is running, without pausing it first. Just be prepared for wonky test results or a temporary hiccup in test traffic if you do this.
This command queries the running k6 instance and prints all collected performance metrics:
extensive output from k6 stats
Starting k6 in one terminal window, and controlling it from another window on the same machine may not seem very "remote”, but you can control k6 instances anywhere, as long as you can communicate with the machines where they are running.
What happens behind the scenes here is that the original k6 process starts an HTTP server, exposing a REST API on localhost:6565. Other k6 instances can connect to this server, and issue commands by talking to the API end points.
By default, k6 scale and the other commands will assume you want to talk to a k6 process that is running its API server on localhost:6565, but you can use the -a/--address command line option to specify both the bind address/port for the API server (e.g. k6 run --address 188.8.131.52:5678 --paused myscript.js) and where the k6 that you want to control is located (k6 scale --address 184.108.40.206:5678 --vus 50).
- k6 pause - pauses test execution, halting all VUs
- k6 resume - unpauses k6, causing all active VUs to resume execution
- k6 scale - change the number of active VUs (or the max number of VUs allowed)
- k6 stats - report current statistics that have been collected
- k6 status - report general status for the test