Skip to content

Web UI

The control plane serves a built-in web UI at its public URL (default http://localhost:8080 after Docker Compose). You can run the full load-test loop from the browser — no YAML required.

Terminal window
make quickstart
make docker-open # or: test-scale open
# Open the UI URL printed at the end of quickstart

The header shows the deployment mode (Docker / Kubernetes / Ingress), the public URL, and the build version.

If TEST_SCALE_API_KEY is set on the control plane (Compose sets a local key), protected API calls prompt for the key once. The UI stores it in sessionStorage as X-Test-Scale-Key for later requests.

With Docker Compose, make docker-open / make docker-run already use the key from deploy/docker/scripts/ports.sh. If the prompt appears, paste the same value (local-dev-key in the default Compose stack, or whatever your .ports.env / Helm notes print).

Tab Purpose
Submit Create a plan (or reuse a saved one) and start a run
Runs Live table of recent runs — stop, re-run, open Grafana
Compare Diff two completed runs (RPS, latency, errors, cost)
Dashboard Embedded Grafana view for a selected run
  1. Choose New configuration or Saved plan.
  2. Fill the form (or pick a saved plan to re-run its stored request).
  3. Click Start Run.
Field Notes
Plan / run name Optional labels for history
Target URL In Docker, use http://mock-target or http://host.docker.internal:<port> — not localhost for host apps
Target RPS / duration Aggregate RPS and load duration
Ramp pattern constant, ramp, step, spike
HTTP method / timeout Defaults to GET / 10000 ms
Auth None, Bearer/JWT, session cookie, or custom header
Extra headers JSON object, e.g. {"X-Request-Id":"load-test"}
Body / JSON payload Raw body text; UI sends it as the request body
Expected statuses Comma-separated; empty means any 2xx
SLO (optional) p95 latency (ms) and max error rate

A cost estimate card updates as you change RPS and duration (worker count × configured rate).

If the control plane requires ownership checks (SAFETY_VERIFICATION_TOKEN):

  • localhost / 127.0.0.1 targets skip verification.
  • Remote targets must serve the token at
    {target_url}/.well-known/test-scale-verification
    Use Check target before starting.

The Runs tab auto-refreshes. Each row shows status, slug, target, RPS, p95, errors, SLO, and cost.

Typical actions (per row, depending on state):

  • Stop a running test
  • Re-run a completed plan
  • Open the dashboard for that run’s Grafana view

Slugs look like run-0708-0843-b2ab — use the same IDs with the CLI.

  1. Select a current run and a baseline (same target and load config).
  2. Click Compare.

The UI shows metric deltas (throughput, percentiles, errors, cost) and highlights regressions. For CI gates, use:

Terminal window
test-scale diff -c <current-slug> -b <baseline-slug> --fail-on-regression

The Dashboard tab embeds Grafana for the selected run. Pick a run from the dropdown and Refresh if panels look stale.

Deployment Where Grafana comes from
Docker Compose Separate Grafana port (printed by quickstart, often :3001) and/or in-UI embed via GRAFANA_BASE_URL
Ingress Often /grafana on the same host
Port-forward K8s Forward Grafana service or use the URL configured in Helm values

The UI adapts messaging to the deployment mode:

  • Docker — reminds you that workers are containers; use host.docker.internal for apps on your laptop.
  • Kubernetes (port-forward) — workers scale via KEDA in the cluster.
  • Ingress + TLS — dashboards may load from /grafana on the same host.
Task Best tool
Exploratory runs, demos Web UI
Secrets in plans (${ENV_VAR}) CLI + YAML — expansion happens when the CLI parses the file
CI gates / scripting CLI (--json, --fail-on-regression)
Re-run exact saved plan UI Saved plan or test-scale rerun

Plans and runs created in the UI use the same REST API as the CLI. Environment-variable expansion for secrets is CLI/file only — paste tokens into the UI auth fields for interactive runs, or submit YAML via the CLI.

Terminal window
make docker-open
# or
test-scale open
test-scale open --print # print URL only

Kubernetes without Ingress:

Terminal window
kubectl port-forward -n test-scale svc/test-scale-ctrl-plane 8080:8080
open http://localhost:8080