PerfLoad / self-hosted load testing
Self-Hosted Load Testing: Run the PerfLoad Runner Yourself
Some of the services you most want to load test aren't reachable from the public internet: internal APIs, staging environments, anything behind a VPC. PerfLoad's runner is a Docker image you run yourself, so the machine generating the load can live wherever your target does.
Run PerfLoad Yourself →One docker run command. The installation guide also covers Kubernetes.
How the pieces fit
- Workbench / Dashboard in your browser, or a CI job
- PerfLoad runner (Docker) in your environment
- Service under test
The runner is a single container that serves the Workbench and Dashboard, exposes the REST API, and runs k6 for each test. Your browser (or your pipeline) talks to the runner; the runner is the one that sends requests to the target. That split is the whole idea: what needs to reach the target is the runner, not your laptop. In the Workbench, the runner's address is one global setting under Settings, so you can point the same UI at a local container or a remote one.
Run it
docker run -d --name perfload -p 3000:3000 -v perfload-runs:/app/runs perfload/perfload-runner:latest
-p 3000:3000serves the UI, the API, and the k6 live dashboard on one port.-v perfload-runs:/app/runskeeps run history in a named Docker volume.
Check curl http://localhost:3000/health, then open
http://localhost:3000/load-tester.html.
Why self-host the runner
Reach services that aren't public
A hosted load generator can only test what it can route to. A runner on the same network as your internal service can test it directly, with no need to open a hole to the internet just so a test can get in.
Run close to the target
Putting the runner in the same region, cluster, or VPC as the service takes the public internet out of the measurement. Latency numbers then reflect your service and its immediate network, not the path from wherever a test happened to run.
Keep it inside your private network
The runner can stay in a VPC or private subnet. Whoever needs the UI or API reaches it through the access paths you already manage, such as a VPN, a bastion, or an internal load balancer. PerfLoad's runner API doesn't document built-in authentication, so those network controls are what decide who can start a test.
Control the execution infrastructure
You choose the machine, its CPU and memory, and how many runs happen at once. That matters because each run starts its own k6 process and runs aren't queued: several high-VU tests started together share whatever capacity the host has. The installation guide includes light and heavy resource profiles for Kubernetes.
Keep run history on volumes you own
Run history is stored under /app/runs. With a Docker named volume it survives stopping,
restarting, and upgrading the container; on Kubernetes, mount a PersistentVolumeClaim there. Without persistent
storage, history doesn't survive a restart — and neither will any baseline Run IDs your
CI/CD pipeline depends on.
Updating the runner
Pull the new image, replace the container, and reuse the same volume:
docker pull perfload/perfload-runner:latest
docker stop perfload && docker rm perfload
docker run -d --name perfload \
-p 3000:3000 \
-v perfload-runs:/app/runs \
perfload/perfload-runner:latest
To avoid surprises, pin a version tag instead of latest.
Kubernetes
The installation guide includes a kustomize layout: a Deployment, a PersistentVolumeClaim for
/app/runs, a Service, and a ConfigMap. One constraint to know before scaling: run state is loaded
from disk when the process starts, so run a single replica rather than several behind one Service.
Where PerfLoad Cloud fits
Everything on this page works today with the Docker image. A hosted control plane with a runner deployed into your VPC is planned as PerfLoad Cloud, which is coming soon.
FAQ
Does anything need to be exposed to the internet?
Not by PerfLoad itself. The runner needs to reach your target and whoever uses it needs to reach the runner; both can be private connections.
Can one runner serve several people?
Yes. Anyone who can reach the runner's URL can use its UI and API, and they share one run history. Point the Workbench's runner setting at it.
Can a pipeline use a self-hosted runner?
Yes, as long as the job can reach it. For private networks that usually means a CI agent inside the same network; see GitHub Actions load testing.
Related guides
Put the runner next to what you're testing
Start the container, open the Workbench, and paste a curl command.
Run PerfLoad Yourself →