Change virtual users mid-run
A running test is not fixed. From the run’s Live tab you can move the virtual user target and the throughput cap while the load is in flight, pause and resume it, and every change is recorded on the run’s timeline with who made it and when.
Nothing restarts. The run keeps its id, its result series and its report.
Before you start
Section titled “Before you start”- The run must be running. A queued or finished run answers
409 RUN_NOT_RUNNING. - You need the controller role on the run (account members and test editors have it).
- Your executor and your script must support the control. JMeter, k6, Locust and Gatling can move
virtual users live; the other executors cannot, and the console says so instead of pretending.
Except on Locust, the script also has to be built for it — a Concurrency Thread Group on JMeter, an
externally-controlledscenario on k6, the helper opt-in on Gatling. Make your test controllable mid-run is the recipe per engine; What each executor supports at runtime is the full matrix.
Change the virtual user target
Section titled “Change the virtual user target”-
Open the run and select the Live tab.
-
Set the Virtual users field to the new fleet-wide total and commit it.
The number you type is always the whole fleet. Underneath the field MaxoPerf shows the divide it will perform — for example
2 000 = 20 runners × 100— so what each runner is told is never a guess. -
Watch the ack pill. It counts runners that have confirmed the change:
applied 4 987 / 5 000. It normally converges in well under a second. -
Confirm it landed in the load. The run’s charts get a vertical marker at the moment the change applied, so a step in the VU or throughput series lines up with the change that caused it.
Change the throughput cap
Section titled “Change the throughput cap”Identical flow, using the Requests per second field. 0 means unlimited.
Pause and resume
Section titled “Pause and resume”The Pause toggle stops the load without ending the run — useful when you want to fail something over, take a snapshot, or let a queue drain, and then continue in the same run and the same charts. Resume restores the previous target.
Scope a change to part of the fleet
Section titled “Scope a change to part of the fleet”By default a change applies to every live runner. The scope chips narrow it:
| Scope | Use it for |
|---|---|
| All | the whole fleet (default) |
| Locations | one cloud region, or one private datacenter |
| Runners | named individual runners |
A scope that resolves to zero live runners is rejected with 422 SELECTOR_NO_MATCHING_RUNNERS
rather than accepted and quietly applied to nothing.
Plan limits
Section titled “Plan limits”Increases are capped by your plan’s maxLiveConcurrentVus and maxLiveThroughputRps; going past
them returns 403 PLAN_LIMIT_EXCEEDED. Enterprise sets both to -1 (unlimited), so no mid-run
increase is refused on that plan.
Decreases are never blocked — including from a run that started above the cap. If your test is melting the system under test, you can always turn it down.
From the API
Section titled “From the API”curl -X PUT "$MAXOPERF_API/v1/runs/$RUN_ID/live-controls/virtual-users" \ -H "Authorization: Bearer $MAXOPERF_API_KEY" \ -H "X-Account-Id: $ACCOUNT_ID" \ -H 'Content-Type: application/json' \ -d '{"scope":{"type":"all"},"total":2000}'// 202 Accepted{ "revision": 7, "perRunner": 100, "runnerCount": 20, "dispatchState": "dispatched", "delivered": true }The per-runner share is rounded up and never drops below 1, so a small total across a wide fleet cannot be delivered exactly. When that happens the response says so rather than implying an exact split, and the timeline renders the total as approximate:
// 202 Accepted — 7 RPS across 20 runners is 1 each, so the fleet will really run 20{ "revision": 8, "perRunner": 1, "runnerCount": 20, "clamped": true, "effectiveTotal": 20, … }clamped is absent whenever the divide is exact. If a decrease comes back clamped, the fleet is
too wide for the target — release runners, or accept effectiveTotal as the floor.
Read the outcome back — desired state, capabilities and ack tallies — with
GET /v1/runs/:runId/live-controls, the full change log with
GET /v1/runs/:runId/live-controls/history, and the exact runners that have not applied a revision
with GET /v1/runs/:runId/live-controls/revisions/:revision/acks?status=failed.