Experimental build. loadr — the software and this entire site — was designed and built by Anthropic's Fable model as an experiment in AI-driven engineering.

Rust · single binary · zero dependencies

Find the
breaking point.

loadr brings together the best ideas from k6, JMeter, Gatling and Locust in one place: declarative YAML tests, embedded JavaScript, six protocols, plugins, a built-in live web UI, and distributed execution with mathematically exact percentiles. All in one binary.

$ cargo install --git https://github.com/levantar-ai/loadr loadr-cli
loadr run checkout.yaml
  live-demo — 1 scenario(s), 8.1s

  checks........................: 100.00% — ✓ 752 ✗ 0
    ✓ status is 200 (376 / 376)
    ✓ under 200ms (376 / 376)

  http_req_duration.............: avg=4.96ms med=3.02ms p(95)=10.73ms p(99)=49.38ms
  http_req_tls_handshaking......: avg=0µs (connections reused per VU)
  http_req_waiting..............: avg=4.85ms med=2.90ms p(95)=10.57ms
  http_reqs.....................: 376 (46.66/s)
  iterations....................: 376 (46.66/s)
  vus...........................: value=5 min=4 max=5

  thresholds:
    ✓ http_req_duration: p(95)<500 (observed: 10.73)
    ✓ checks: rate>0.95 (observed: 1.00)
    ✓ http_req_failed: rate<0.01 (observed: 0.00)
7
load executors
6
protocols built in
1
binary, zero deps
p99.9
HDR-exact, fleet-wide

Why loadr

Four tools' best ideas. One Rust binary.

loadr draws, with thanks, on four projects that shaped load testing: k6's execution model, JMeter's request arsenal, Gatling's flow-control DSL and feeders, and Locust's behaviour model — brought together and reimplemented in Rust. See what we built on →

Honest load, honest numbers

Open-model arrival-rate executors keep the offered load constant even when your system slows down — saturation shows up as dropped_iterations, not silently lower RPS. Every latency is an HDR histogram: p(99.9) is exact, never estimated, never averaged.

Tests you can code-review

Declarative YAML with a generated JSON Schema — your editor autocompletes it, loadr validate lints it with line numbers and did-you-mean fixes, and the diff in your PR actually means something. Drop into JavaScript exactly where logic demands it.

A platform, not just a CLI

Built-in management web UI (think RabbitMQ for load tests), distributed controller/agent mode over mTLS gRPC, six metric exporters, WASM & native plugins, and importers that eat your existing .jmx plans and k6 scripts.

See it in action

Real recordings. Real runs. No mockups.

Every clip is the actual loadr binary executing against a live server.

View all 22 demos →

The live web UI, mid-run

Live charts, threshold pills, run controls, editor and fleet view — a real browser session.

0:40

The quickstart 0:24

A distributed fleet, live 0:34

Everything, in the box

The exhaustive feature list

If it's listed, it ships in the binary — and every item links to its documentation.

All 7 k6 executors

constant-vus, ramping-vus, constant-arrival-rate, ramping-arrival-rate, per-vu-iterations, shared-iterations, externally-controlled — identical semantics, open and closed models.

Concurrent scenarios

Any number of named scenarios per test with independent executors, stages, start times, graceful stop and ramp-down — browsers, API clients and batch jobs in one run.

Thresholds as CI gates

p(95)<400, rate>0.99, any percentile, tag-filtered selectors, abort_on_fail circuit breakers with warm-up delay. Exit code 99 on failure — k6-compatible.

Checks + JMeter assertions

k6-style checks that never fail requests, and JMeter-style assertions that do: status, body contains/regex, JSONPath, XPath, duration, size, headers, JS expressions — with abort actions.

Correlation & extraction

JSONPath, regex capture groups, XPath 1.0, CSS selectors, boundary extractors and headers — extracted values flow into later requests as ${name} and into JS.

Data-driven testing

CSV & JSON feeders with sequential, random or shuffle strategies (shared or per-VU, recycle or stop-at-EOF), inline rows, and secrets that never reach logs.

Flow control & weighted tasks

repeat, while, if/else and weighted / uniform / round-robin random branches — Gatling's loops and switches and Locust's weighted-task model, in declarative YAML.

Throttling

A global request-rate ceiling (throttle: { requests_per_second }) on top of any executor — Gatling's reachRps, for staying under a known rate limit no matter how fast the target is.

Embedded JavaScript

QuickJS per VU with k6-style imports (k6/http, check, sleep, metrics), setup()/teardown(), scenario functions, beforeRequest/afterRequest hooks, inline ${js: …} — sandboxed with time & memory limits.

Timers & pacing

Constant, uniform-random and gaussian think time; constant-throughput pacing (the JMeter timer, done right); per-scenario and global defaults.

Phase-level HTTP timings

DNS, connect, TLS handshake, send, TTFB and receive measured per request on a hand-built hyper stack — plus exact wire-level byte counts. No averaged guesses.

Cookies, redirects, bodies

Automatic per-VU RFC 6265 cookie jars with manual override, redirect policies, JSON/form/multipart/file bodies, query params — everything interpolated.

TLS, mTLS, proxies, HTTP/2+

Custom CAs, client certificates, SNI override, insecure mode for staging, HTTP/HTTPS proxies (CONNECT), ALPN negotiation with version forcing — all rustls, no OpenSSL.

Environment overlays

One file, many targets: loadr run -e staging deep-merges named overlays — gentler CI load, staging URLs, relaxed thresholds, without copy-paste.

6 metric exporters

JSON lines, CSV, Prometheus (scrape + remote-write), InfluxDB line protocol, OpenTelemetry OTLP (gRPC & HTTP), StatsD — plus a pre-built Grafana dashboard in the repo.

WASM + native plugins

Five plugin types (protocol, output, extractor, assertion, service) over two mechanisms: sandboxed WASM components with a WIT interface, and abi_stable native libraries. No rebuilds, ever.

Distributed by design

Controller + agents over gRPC with optional mTLS: load partitioning, synchronized starts, data-file shipping, heartbeats, reconnection, agent-loss policies — and central HDR merging.

Built-in web UI

Live dashboards over SSE, a test editor with one-click validation, run history, pause/stop/scale controls, agent fleet view, log tail — embedded in the binary, dark mode native.

JMeter & k6 importers

loadr convert plan.jmx translates thread groups, samplers, timers, assertions, extractors and CSV configs; the k6 importer maps options, scenarios, checks and http calls — with clear warnings for the rest.

Reports & tooling

k6-style console summaries, JSON export, self-contained HTML reports (loadr report), shell completions, JSON Schema output, structured logs, --quiet/-v spectrum.

Show me

From smoke test to fleet-scale in the same file

checkout.yamldeclarative, schema-validated
name: checkout-under-load
defaults:
  http: { base_url: https://shop.example.com }

data:
  users: { type: csv, path: users.csv, mode: shared, on_eof: recycle }

scenarios:
  shoppers:
    executor: ramping-vus
    stages: [ { duration: 2m, target: 100 }, { duration: 5m, target: 100 } ]
    think_time: { type: uniform, min: 1s, max: 3s }
    flow:
      - request:
          url: /login
          method: POST
          body: { form: { user: "${data.users.username}", pass: "${data.users.password}" } }
          extract:
            - { type: css, name: csrf, expression: "input[name=csrf]", attribute: value }
          assert:
            - { type: status, equals: 200 }
      - request:
          method: POST
          url: /cart
          body: { form: { sku: W-1, csrf: "${csrf}" } }
          checks:
            - { type: status, equals: 201 }
            - { type: duration, name: fast checkout, max: 300ms }

thresholds:
  http_req_duration: [ "p(95)<400", "p(99.9)<1500" ]
  http_req_failed: [ { threshold: "rate<0.01", abort_on_fail: true } ]
  checks: [ "rate>0.99" ]

Protocols

Six protocols. Full metrics on every one.

Every protocol reports DNS, connect, TLS, TTFB, duration, and bytes sent/received — and works with the same extract/assert/check blocks.

HTTP/1.1 + 2

- request:
    method: POST
    url: /orders
    body: { json: { sku: W-1, qty: 2 } }
    checks: [ { type: status, equals: 201 } ]

ALPN, prior-knowledge h2, keep-alive tuning, per-VU pools.

WebSocket

- request:
    url: wss://chat.example.com/ws
    ws:
      send: [ '{"type":"hello"}' ]
      receive_until: '"ack"'
      session_duration: 10s

Subprotocols, binary frames, message counters, session metrics.

gRPC

- request:
    url: grpc://svc:50051
    grpc:
      reflection: true        # or proto_files
      service: helloworld.Greeter
      method: SayHello
      message: { name: "vu-${vu}" }

Unary + all streaming shapes, in-process proto compile — no protoc.

GraphQL

- request:
    url: /graphql
    protocol: graphql
    graphql:
      query: "query($t:String!){ search(t:$t){ id } }"
      variables: { t: widget }

GraphQL error semantics, partial-error awareness, own metric family.

TCP

- request:
    url: tcp://gateway:7000
    socket:
      send_text: "PING\r\n"
      read_bytes: 64
    checks: [ { type: body_contains, value: PONG } ]

Exact byte accounting; regex/boundary extraction over raw payloads.

UDP

- request:
    url: udp://stats:8125
    socket:
      send_hex: "deadbeef 0102"
      read_timeout: 500ms

Datagram round trips with hex payloads and loss-aware timeouts.

Need MQTT, Kafka, or your in-house protocol? Write a protocol plugin — no fork, no rebuild.

Distributed

Most tools average percentiles across nodes. That number is wrong.

If agent A's p99 is 100 ms and agent B's is 1000 ms, the fleet's true p99 is not 550 ms. loadr agents stream HDR histogram deltas every second; the controller merges the histograms — a lossless operation — and computes percentiles only after the merge. Thresholds evaluate centrally against fleet-wide truth.

  • VU counts and arrival rates partitioned exactly across agents — global ramps stay precise
  • Synchronized start barrier, heartbeats, jittered reconnection, agent-loss policies
  • Test definitions and CSV/proto/JS files shipped to agents automatically
  • One bidirectional gRPC stream per agent, plaintext or mTLS
  • Docker Compose stack and Helm chart in the repo: agents.replicas=10 and go
controller
partition · merge · thresholds · UI
│ gRPC · mTLS │
agent-1
200 rps
agent-2
200 rps
agent-3
200 rps
// verified by the test suite:
agents see 1–1000ms and 1001–2000ms
merged p99 = 1980ms ✓ (true union p99)
averaged p99 = 1485ms ✗ (what others report)

Management UI

RabbitMQ-style management, for load tests

Embedded in the binary. loadr run --ui for a single run, or the full fleet console on the controller. Edit and validate tests in the browser, watch live percentiles, pause, stop, or turn the VU dial mid-run.

loadr · overview
live · run 4588f1bf
Requests / s
612.4
Active VUs
300
p95 latency
187 ms
Error rate
0.02%
✓ p(95)<400 — 187.2 ✓ rate<0.01 — 0.0002 ✓ checks rate>0.99 — 0.998 ⏸ Pause ■ Stop

Test library & editor

Save, edit and validate YAML in the browser — diagnostics jump to the line.

Run history

Every run's full summary persisted: trends, checks, thresholds, pass/fail.

Fleet view

Agent health, active VUs, cores, labels, last heartbeat — at a glance.

Auth built in

HTTP Basic and bearer tokens; loopback-only by default. JSON API for everything.

How loadr compares

loadr next to k6, JMeter, Gatling & Locust

All four are excellent, widely-loved tools that shaped this space — this is simply where loadr sits relative to them; pick whatever fits your team. Where a cell says Enterprise or cloud, the capability exists in that project's paid/hosted tier. See also what loadr is built on.

k6 JMeter Gatling Locust loadr
Test formatJavaScriptXML (GUI)Scala / Java / Kotlin DSLPythonYAML + JS, JSON-Schema validated
Open-model load (arrival rate)plugin✓ injection profilescustom shapes✓ all 7 executors
Protocols built inHTTP, WS, gRPCmanyHTTP, WS, SSE, JMSHTTP (custom clients)HTTP/1.1+2, WS, gRPC + reflection, GraphQL, TCP, UDP
Assertions / extractors / timerschecks✓ fullchecks + pausesin Python✓ JSONPath, XPath, CSS, regex, boundary; 3 timers + pacing
Flow control & feeders (Gatling-style)codecontrollers✓ DSLin Python✓ repeat/while/if/switch/foreach + feeders + throttle
Extensions without rebuilding— (xk6 recompile)jars— (Scala recompile)Python✓ WASM (sandboxed) + native plugins
Distributed executioncloudRMIEnterprise✓ master / worker✓ built-in, gRPC + mTLS
Fleet-wide percentilescloudaveragedEnterpriseapproximate✓ exact (HDR histogram merge)
Live management UIcloudEnterprise✓ built-in✓ embedded
Per-phase timings (DNS/TLS/TTFB)partial✓ on every protocol
Runtime footprintGo binaryJVM + tuningJVMPython runtimeone Rust binary, distroless image
Migration path in✓ imports .jmx and k6 scripts

Standing on shoulders

What loadr is built on

loadr is a fresh Rust implementation — not a fork of anything — but it takes the best ideas from four tools that defined load testing, deliberately and with thanks.

k6

the model

The execution model is k6's: the seven executors, open/closed load, the four metric types, thresholds with abortOnFail and exit code 99, checks and groups — and an embedded-JS experience so close the API is import-compatible (import http from 'k6/http').

Apache JMeter

the arsenal

JMeter shaped the request toolkit: response / duration / size / JSONPath / XPath assertions; regex, boundary, CSS and XPath extractors; constant / uniform / gaussian and constant-throughput timers; CSV data sets and cookie management. loadr convert reads your .jmx plans.

Gatling

the DSL

Gatling gave loadr its flow control — repeat, while, if/else and the random / uniform / round-robin switch — plus feeder strategies (sequential / random / shuffle), JSON feeders, and the request-rate throttle.

Locust

the behaviour model

Locust's weighted-task model — users picking @task(weight) actions at random — is exactly loadr's weighted random step. Its clean real-time UI inspired loadr's management UI, and its master/worker model informed the controller/agent design.

The combination is the point: k6's model and JMeter's arsenal and Gatling's DSL and Locust's behaviour model — in one binary, with correct distributed percentiles, a plugin system and six protocols, rarely found together in a single tool. Full credits →

Trademarks and project names belong to their respective owners. loadr is independent and not affiliated with or endorsed by k6/Grafana Labs, the Apache Software Foundation, Gatling Corp, or the Locust project.

Roadmap

What's coming

loadr already covers the core of k6, JMeter, Gatling and Locust. Here's where it's headed next — shaped by what those tools and their plugin ecosystems do that loadr doesn't yet. No dates, just direction; priorities shift with feedback.

Just shipped: SQL load testing (PostgreSQL & MySQL), the time-series HTML report, JMESPath & fused check-chains, and the in-UI failure & error breakdown.

Next up

  • Scriptable protocol clients in JS
    Drive WebSocket and gRPC from JavaScript, plus http.batch and an async event loop / timers.
  • Server-side resource monitoring
    Correlate CPU / memory / disk / network of the system-under-test with your load — JMeter's PerfMon, built in.
  • Programmable load shapes
    Compute load per-tick in code, richer injection profiles (atOnceUsers, nothingFor, stepped ramps), and throughput-shaping profiles that adjust concurrency to hold a target RPS.

Planned

  • Proxy recorder
    loadr record — capture real browser/API traffic and generate a test.
  • Manual pass/fail from JS
    Mark a response failed/succeeded in script (Locust catch_response-style).
  • Messaging protocols
    Kafka, MQTT, JMS and AMQP — likely as plugins on the existing plugin ABI.
  • Inter-VU coordination & auto-stop
    Pass data between virtual users at runtime, and stop a run automatically when error-rate or latency guards trip.

Exploring

  • Managed outputs & dashboards
    More exporters and hosted run-over-run trend comparison.
  • Distributed niceties
    --expect-workers gating and custom controller↔agent messages.
  • Plugin registry
    A browsable catalog of community WASM & native plugins.

Want something prioritised? It probably came from k6, JMeter, Gatling or Locust — tell us which workflow you're missing.

Install

Running in under a minute

Binary (Linux / macOS / Windows)
$ curl -sSL https://github.com/levantar-ai/loadr/releases/latest/download/loadr-x86_64-unknown-linux-gnu.tar.gz | tar xz
$ sudo mv loadr-*/loadr /usr/local/bin/
$ loadr version
Cargo
$ cargo install --git \
    https://github.com/levantar-ai/loadr loadr-cli

# no system deps: no protoc,
# no OpenSSL, no JVM, no node
All platforms
# macOS (Intel + Apple Silicon), Windows,
# Linux x86_64 + arm64 — every build, with
# SHA256 checksums and SLSA provenance:
# github.com/levantar-ai/loadr/releases
First test
$ loadr validate examples/01-quickstart.yaml   # line-numbered diagnostics, did-you-mean fixes
$ loadr run examples/01-quickstart.yaml        # exit 0 = thresholds passed, 99 = failed
$ loadr run --ui examples/02-ramping-load.yaml # live dashboard at http://127.0.0.1:6464
$ loadr report results.json -o report.html     # self-contained HTML report

27 runnable examples ship in the examples/ folder of every download — ramp, spike and soak tests, data-driven logins, WebSocket chat, gRPC streaming, GraphQL, Redis, SSE, headless-browser timing, raw sockets, environment overlays and a distributed fleet test. Browse all 34 →

The documentation is exhaustive.

A getting-started path, the complete YAML reference, the full JS API, every protocol, distributed operations, plugin development with worked examples, and k6 and JMeter migration guides — everything you need to go from zero to a production load test.