Capacity And Runners
How TestVibe executes work, what the capacity settings actually control, and how to give a self-hosted install more of it.
Two containers, three kinds of work
TestVibe ships one runner image that runs in two modes. There is no separate load runner — load shares the test runner.
runner
RUNNER_MODE=run
test runs and load runs
egress-restricted
browser
RUNNER_MODE=generation
test generation and the assistant
reaches the sites you point it at
They are split because they need different network access. Generation and the assistant drive arbitrary URLs interactively while someone watches; test runs execute code against the site you configured. Keeping them apart means the interactive path cannot quietly become the execution path.
On Compose these are the runner and browser services. On Kubernetes they are the -runner and -browser Deployments. On the appliance they are testvibe-runner.service (port 8081) and testvibe-browser.service (port 8082), both bound to loopback — nothing is reachable from outside the VM.
Admission caps: how much is started at once
These are the settings you will normally touch. Administration console → Capacity. They are stored in the instance database and applied live — no restart.
TV_SANDBOX_LOCKED_MAX
concurrent test runs
TV_SANDBOX_LOAD_MAX
concurrent load runs
TV_SANDBOX_GENERATION_MAX
concurrent test generations
TV_SANDBOX_ROAMING_MAX
concurrent assistant sessions
Each kind of work has its own budget so a burst of one cannot starve another — a queue of generations will not stop tests running.
These caps throttle; they do not create capacity. Raising a cap above what your hardware can actually run does not make anything faster. Work that cannot start queues — the pool waits up to 30 minutes for a free slot before failing — so the symptom of an over-set cap is slow runs, not more of them.
Load runs shard: a single 100-VU run spreads across roughly five slots, which is why TV_SANDBOX_LOAD_MAX defaults higher than the others.
Real capacity: scale UP, not out
A self-hosted install runs one runner and one browser host, by design. Adding more of either does not spread the load — it loses work. Run state lives in the process that accepted the job, and TestVibe polls that same endpoint afterwards to follow progress. Put a second instance behind the same address and some of those polls reach a process that never saw the job.
So capacity comes from giving the single runner more CPU:
Give the VM more vCPU and memory. 4 vCPU / 8 GB is a sensible floor; a busy install wants more. Nothing to configure — both units are installed and enabled already.
Environment-level changes go in /etc/testvibe/*.env, then:
Those files live on the data disk, so your edits survive an upgrade that replaces the OS disk.
Raise the runner's resources rather than its replica count:
runner.replicaCount and browser.replicaCount must stay 1. The chart refuses to render otherwise, with an explanation — an install-time error rather than runs that go missing later.
Keep shmSize at 1Gi or higher. Chromium crashes on the 64 MB default in ways that look exactly like flaky tests.
Give the host more CPU. docker compose up --scale runner=N is not supported and Compose will refuse it.
If the host is shared, cap what the runner may take:
Sizing
Test runners are the component that decides how much machine you need, because Playwright drives real browsers. As a starting point:
Evaluation, a few runs at a time
4
8 GB
A team, runs through the working day
8
16 GB
Continuous runs, or load testing
16+
32 GB+
Set the admission caps to roughly what the hardware supports and adjust from what you observe. Runs queuing steadily means you are at the ceiling; runs failing on timeouts usually means a cap set well above it.
When one machine is not enough
There is no supported way to run TestVibe's execution tier across several machines today. The ceiling is one runner on one host, scaled vertically. If you reach it, talk to us — the fix is per-replica addressing in the application, not a configuration change you can make.
Related Help
Last updated
Was this helpful?
