Load Testing
Every other run kind checks whether something is correct. Load testing checks something different: whether it holds up under concurrent traffic. Give it one target, how many virtual users to run at once, and for how long, and VeriWasp fires requests at that target for the whole duration, then reports latency percentiles, throughput, and error rate.
This is deliberately HTTP-level, not real browser instances. Running dozens of concurrent Chrome processes to simulate concurrent users would be slow and expensive; a lightweight request replayer against a single endpoint gets you the same signal (does this endpoint hold up under load) without it.
Creating a load test
Go to My Runs → New Load Test, or Load Tests in the top nav. Fill in:
- Target URL: the single endpoint every virtual user hits.
- Method, plus optional headers and a body (for POST/PUT/PATCH).
- Virtual users (concurrency): how many requests run at once, up to 50.
- Duration: how long to sustain that load, from 5 to 60 seconds.
- Pass/fail thresholds (optional): a max p95 latency in milliseconds, a max error rate percentage, or both. Leave both blank for a purely informational run.
Creating a load test costs nothing, the same two-step model as every other run kind. Nothing is charged until you trigger it.
Pacing
Each virtual user is capped at 20 requests per second. Without a cap, a single virtual user hitting a very fast endpoint (a cached response, a trivial health check) could fire tens of thousands of requests per second in a tight loop, and at the maximum concurrency and duration that adds up to a real flood, not a lite load test. The cap only kicks in against fast targets; against anything whose real response time is already above 50ms per request, it has no effect; you're still measuring the target's own limits, not VeriWasp's.
Pricing
Unlike every other run kind, a load test is priced by how much load it generates rather than a flat rate, since its actual cost scales with configuration in a way the others don't. It costs 1 credit per 100 "user-seconds" (virtual users × duration), rounded up, with a floor of 1 credit. 10 virtual users for 15 seconds (VeriWasp's defaults) is 2 credits; the maximum configuration, 50 virtual users for 60 seconds, is 30 credits.
Reading the results
Once a run finishes, the report shows:
- Total requests and errors, throughput (requests/second), and error rate.
- Latency percentiles: p50, p95, p99, plus min and max.
- A requests-per-second chart, one bar per second of the run, with any errors in that second shown as a red segment within the bar.
A request is counted as an error if it fails at the transport level (a timeout, a connection refused) or gets a 4xx/5xx response. Unlike API testing, there's no retry: an error during a load test is the exact signal being measured, not a transient condition to smooth over.
If you set a threshold, the run is marked failed when it's breached, with a banner explaining which one. A run with no thresholds configured can never fail on its own results; it's informational.
Sharing
Every load test gets a public link at /load-report/{slug}, shown once it's been run: read-only, no trigger button, same content as the private detail page.
Triggering from CI/CD
Like every other run kind, a load test gets its own secret trigger URL (shown on the detail page) that a deploy pipeline can POST to, at /load-test-trigger/{token}.
Gate mode
Add ?wait=<seconds> to block until the run finishes, same as a playtest's CI/CD gate mode, up to a 90 second maximum wait:
curl -X POST "https://veriwasp.com/load-test-trigger/{token}?wait=60"
{
"run_id": "3f1e2c9a-...",
"status": "completed",
"report_url": "https://veriwasp.com/load-report/f8a2c1",
"total_requests": 1500,
"total_errors": 0,
"p50_ms": 42,
"p95_ms": 118,
"p99_ms": 210,
"throughput_rps": 100.0,
"error_rate_pct": 0.0,
"threshold_breached": false
}
status is "failed" whenever a configured threshold was breached, so a load test with a p95 or error-rate threshold set can gate a deploy exactly like a failed playtest step or API assertion. There's no regressions_found for this run kind: there's no baseline/lineage comparison for load test runs, so ?gate=regression is a no-op here.
If the wait budget runs out first, you get the same fire-and-forget response as not passing ?wait= at all, plus a status_url you can poll yourself at /api/load-tests/{slug}/status.