{"slug": "loadr-a-rust-load-testing-tool-that-began-as-a-single-claude-prompt", "title": "Loadr – a Rust load-testing tool that began as a single Claude prompt", "summary": "Loadr, a Rust-based load-testing tool that began as a single Claude prompt, launches with features combining k6, JMeter, Gatling, and Locust. The tool offers declarative YAML tests, embedded JavaScript, six protocols, a live web UI, and distributed execution with exact percentiles, all in a single binary.", "body_md": "#\nFind the\n\nbreaking point.\n\n**loadr** brings together the best ideas from k6, JMeter,\nGatling and Locust in one place: declarative YAML tests, embedded JavaScript, six protocols, plugins,\na built-in live web UI, and distributed execution with\n*mathematically exact percentiles*. All in one binary.\n\n```\n  live-demo — 1 scenario(s), 8.1s\n\n  checks........................: 100.00% — ✓ 752 ✗ 0\n    ✓ status is 200 (376 / 376)\n    ✓ under 200ms (376 / 376)\n\n  http_req_duration.............: avg=4.96ms med=3.02ms p(95)=10.73ms p(99)=49.38ms\n  http_req_tls_handshaking......: avg=0µs (connections reused per VU)\n  http_req_waiting..............: avg=4.85ms med=2.90ms p(95)=10.57ms\n  http_reqs.....................: 376 (46.66/s)\n  iterations....................: 376 (46.66/s)\n  vus...........................: value=5 min=4 max=5\n\n  thresholds:\n    ✓ http_req_duration: p(95)<500 (observed: 10.73)\n    ✓ checks: rate>0.95 (observed: 1.00)\n    ✓ http_req_failed: rate<0.01 (observed: 0.00)\n```\n\nWhy loadr\n\n## Four tools' best ideas. One Rust binary.\n\nloadr 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 →](#credits)\n\n### Honest load, honest numbers\n\nOpen-model arrival-rate executors keep the *offered* load constant even when your\nsystem slows down — saturation shows up as `dropped_iterations`\n\n,\nnot silently lower throughput (requests per second, RPS). Every latency is an HDR histogram: `p(99.9)`\n\nis exact, never estimated, never averaged.\n\n### Tests you can code-review\n\nDeclarative YAML with a generated JSON Schema — your editor autocompletes it,\n`loadr validate`\n\nlints it with line numbers and\ndid-you-mean fixes, and the diff in your PR actually means something.\nDrop into JavaScript exactly where logic demands it.\n\n### A platform, not just a CLI\n\nBuilt-in management web UI (think RabbitMQ for load tests), distributed\ncontroller/agent mode over mTLS gRPC, six metric exporters, WASM & native plugins,\nand importers that eat your existing `.jmx`\n\nplans and k6 scripts.\n\nSee it in action\n\n## Real recordings. Real runs. No mockups.\n\nEvery clip is the actual `loadr`\n\nbinary executing against a live server.\n\n[View all 22 demos →](/demos/)\n\n### The live web UI, mid-run\n\nLive charts, threshold pills, run controls, editor and fleet view — a real browser session.\n\n### The quickstart 0:24\n\n### A distributed fleet, live 0:34\n\nEverything, in the box\n\n## The exhaustive feature list\n\nIf it's listed, it ships in the binary — and every item links to its documentation.\n\n### All 7 k6 executors\n\n`constant-vus`\n\n, `ramping-vus`\n\n, `constant-arrival-rate`\n\n, `ramping-arrival-rate`\n\n, `per-vu-iterations`\n\n, `shared-iterations`\n\n, `externally-controlled`\n\n— identical semantics, open and closed models.\n\n### Concurrent scenarios\n\nAny 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.\n\n### Thresholds as CI gates\n\n`p(95)<400`\n\n, `rate>0.99`\n\n, any percentile, tag-filtered selectors, `abort_on_fail`\n\ncircuit breakers with warm-up delay. Exit code 99 on failure — k6-compatible.\n\n### CI-native: GitHub Action + JUnit\n\nA first-party `setup-loadr`\n\n/ `run`\n\naction installs the CLI and runs your plan, and `--junit`\n\nemits a JUnit report every CI test panel renders — GitHub, GitLab, Jenkins, CircleCI.\n\n### Checks + JMeter assertions\n\nk6-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.\n\n### Correlation & extraction\n\nJSONPath, regex capture groups, XPath 1.0, CSS selectors, boundary extractors and headers — extracted values flow into later requests as `${name}`\n\nand into JS.\n\n### Data-driven testing\n\nCSV & JSON feeders with sequential, **random** or **shuffle** strategies (shared or per virtual user (VU), recycle or stop-at-EOF), inline rows, and secrets that never reach logs.\n\n### Flow control & weighted tasks\n\n`repeat`\n\n, `while`\n\n, `if`\n\n/`else`\n\nand weighted / uniform / round-robin `random`\n\nbranches — Gatling's loops and switches and Locust's weighted-task model, in declarative YAML.\n\n### Throttling\n\nA global request-rate ceiling (`throttle: { requests_per_second }`\n\n) on top of any executor — Gatling's `reachRps`\n\n, for staying under a known rate limit no matter how fast the target is.\n\n### Embedded JavaScript\n\nQuickJS per VU with k6-style imports (`k6/http`\n\n, `check`\n\n, `sleep`\n\n, metrics), `setup()`\n\n/`teardown()`\n\n, scenario functions, `beforeRequest`\n\n/`afterRequest`\n\nhooks, inline `${js: …}`\n\n— sandboxed with time & memory limits.\n\n### Timers & pacing\n\nConstant, uniform-random and gaussian think time; constant-throughput pacing (the JMeter timer, done right); per-scenario and global defaults.\n\n### Phase-level HTTP timings\n\nDNS, 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.\n\n### Cookies, redirects, bodies\n\nAutomatic per-VU RFC 6265 cookie jars with manual override, redirect policies, JSON/form/multipart/file bodies, query params — everything interpolated.\n\n### TLS, mTLS, proxies, HTTP/2+\n\nCustom CAs, client certificates, SNI override, insecure mode for staging, HTTP/HTTPS proxies (CONNECT), ALPN negotiation with version forcing — all rustls, no OpenSSL.\n\n### Environment overlays\n\nOne file, many targets: `loadr run -e staging`\n\ndeep-merges named overlays — gentler CI load, staging URLs, relaxed thresholds, without copy-paste.\n\n### 6 metric exporters\n\nJSON lines, CSV, Prometheus (scrape + remote-write), InfluxDB line protocol, OpenTelemetry OTLP (gRPC & HTTP), StatsD — plus a pre-built Grafana dashboard in the repo.\n\n### WASM + native plugins\n\nFive 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.\n\n### Distributed by design\n\nController + agents over gRPC with optional mTLS: load partitioning, synchronized starts, data-file shipping, heartbeats, reconnection, agent-loss policies — and central HDR merging.\n\n### Built-in web UI\n\nLive 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.\n\n### JMeter & k6 importers\n\n`loadr convert plan.jmx`\n\ntranslates 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.\n\n### Reports & tooling\n\nk6-style console summaries, JSON export, self-contained HTML reports (`loadr report`\n\n), shell completions, JSON Schema output, structured logs, `--quiet`\n\n/`-v`\n\nspectrum.\n\nShow me\n\n## From smoke test to fleet-scale in the same file\n\n```\nname: checkout-under-load\ndefaults:\n  http: { base_url: https://shop.example.com }\n\ndata:\n  users: { type: csv, path: users.csv, mode: shared, on_eof: recycle }\n\nscenarios:\n  shoppers:\n    executor: ramping-vus\n    stages: [ { duration: 2m, target: 100 }, { duration: 5m, target: 100 } ]\n    think_time: { type: uniform, min: 1s, max: 3s }\n    flow:\n      - request:\n          url: /login\n          method: POST\n          body: { form: { user: \"${data.users.username}\", pass: \"${data.users.password}\" } }\n          extract:\n            - { type: css, name: csrf, expression: \"input[name=csrf]\", attribute: value }\n          assert:\n            - { type: status, equals: 200 }\n      - request:\n          method: POST\n          url: /cart\n          body: { form: { sku: W-1, csrf: \"${csrf}\" } }\n          checks:\n            - { type: status, equals: 201 }\n            - { type: duration, name: fast checkout, max: 300ms }\n\nthresholds:\n  http_req_duration: [ \"p(95)<400\", \"p(99.9)<1500\" ]\n  http_req_failed: [ { threshold: \"rate<0.01\", abort_on_fail: true } ]\n  checks: [ \"rate>0.99\" ]\n```\n\nProtocols\n\n## Six protocols. Full metrics on every one.\n\nEvery protocol reports DNS, connect, TLS, TTFB, duration, and bytes sent/received — and works with the same extract/assert/check blocks.\n\n### HTTP/1.1 + 2\n\n```\n- request:\n    method: POST\n    url: /orders\n    body: { json: { sku: W-1, qty: 2 } }\n    checks: [ { type: status, equals: 201 } ]\n```\n\nALPN, prior-knowledge h2, keep-alive tuning, per-VU pools.\n\n### WebSocket\n\n```\n- request:\n    url: wss://chat.example.com/ws\n    ws:\n      send: [ '{\"type\":\"hello\"}' ]\n      receive_until: '\"ack\"'\n      session_duration: 10s\n```\n\nSubprotocols, binary frames, message counters, session metrics.\n\n### gRPC\n\n```\n- request:\n    url: grpc://svc:50051\n    grpc:\n      reflection: true        # or proto_files\n      service: helloworld.Greeter\n      method: SayHello\n      message: { name: \"vu-${vu}\" }\n```\n\nUnary + all streaming shapes, in-process proto compile — no protoc.\n\n### GraphQL\n\n```\n- request:\n    url: /graphql\n    protocol: graphql\n    graphql:\n      query: \"query($t:String!){ search(t:$t){ id } }\"\n      variables: { t: widget }\n```\n\nGraphQL error semantics, partial-error awareness, own metric family.\n\n### TCP\n\n```\n- request:\n    url: tcp://gateway:7000\n    socket:\n      send_text: \"PING\\r\\n\"\n      read_bytes: 64\n    checks: [ { type: body_contains, value: PONG } ]\n```\n\nExact byte accounting; regex/boundary extraction over raw payloads.\n\n### UDP\n\n```\n- request:\n    url: udp://stats:8125\n    socket:\n      send_hex: \"deadbeef 0102\"\n      read_timeout: 500ms\n```\n\nDatagram round trips with hex payloads and loss-aware timeouts.\n\nNeed MQTT, Kafka, or your in-house protocol? [Write a protocol plugin](/docs/plugins/overview.html) — no fork, no rebuild.\n\nDistributed\n\n## Most tools average percentiles across nodes. That number is wrong.\n\nIf agent A's p99 is 100 ms and agent B's is 1000 ms, the fleet's true p99 is\n*not* 550 ms. loadr agents stream **HDR histogram deltas**\nevery second; the controller **merges the histograms** — a lossless\noperation — and computes percentiles only after the merge. Thresholds evaluate centrally\nagainst fleet-wide truth.\n\n- ▸ VU counts and arrival rates partitioned exactly across agents — global ramps stay precise\n- ▸ Synchronized start barrier, heartbeats, jittered reconnection, agent-loss policies\n- ▸ Test definitions and CSV/proto/JS files shipped to agents automatically\n- ▸ One bidirectional gRPC stream per agent, plaintext or mTLS\n- ▸ Docker Compose stack and Helm chart in the repo:\n`agents.replicas=10`\n\nand go\n\npartition · merge · thresholds · UI\n\n200 rps\n\n200 rps\n\n200 rps\n\nManagement UI\n\n## RabbitMQ-style management, for load tests\n\nEmbedded in the binary. `loadr run --ui`\n\nfor 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.\n\n#### Test library & editor\n\nSave, edit and validate YAML in the browser — diagnostics jump to the line.\n\n#### Run history\n\nEvery run's full summary persisted: trends, checks, thresholds, pass/fail.\n\n#### Fleet view\n\nAgent health, active VUs, cores, labels, last heartbeat — at a glance.\n\n#### Auth built in\n\nHTTP Basic and bearer tokens; loopback-only by default. JSON API for everything.\n\nHow loadr compares\n\n## loadr next to k6, JMeter, Gatling & Locust\n\nAll 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](#credits).\n\n| k6 | JMeter | Gatling | Locust | loadr | |\n|---|---|---|---|---|---|\n| Test format | JavaScript | XML (GUI) | Scala / Java / Kotlin DSL | Python | YAML + JS, JSON-Schema validated |\n| Open-model load (arrival rate) | ✓ | plugin | ✓ injection profiles | custom shapes | ✓ all 7 executors |\n| Protocols built in | HTTP, WS, gRPC | many | HTTP, WS, SSE, JMS | HTTP (custom clients) | HTTP/1.1+2, WS, gRPC + reflection, GraphQL, TCP, UDP |\n| Assertions / extractors / timers | checks | ✓ full | checks + pauses | in Python | ✓ JSONPath, XPath, CSS, regex, boundary; 3 timers + pacing |\n| Flow control & feeders (Gatling-style) | code | controllers | ✓ DSL | in Python | ✓ repeat/while/if/switch/foreach + feeders + throttle |\n| Extensions without rebuilding | — (xk6 recompile) | jars | — (Scala recompile) | Python | ✓ WASM (sandboxed) + native plugins |\n| Distributed execution | cloud | RMI | Enterprise | ✓ master / worker | ✓ built-in, gRPC + mTLS |\n| Fleet-wide percentiles | cloud | averaged | Enterprise | approximate | ✓ exact (HDR histogram merge) |\n| Live management UI | cloud | — | Enterprise | ✓ built-in | ✓ embedded |\n| Per-phase timings (DNS/TLS/TTFB) | ✓ | partial | ✓ | — | ✓ on every protocol |\n| Runtime footprint | Go binary | JVM + tuning | JVM | Python runtime | one Rust binary, distroless image |\n| Migration path in | — | — | — | — | ✓ imports .jmx and k6 scripts |\n\nStanding on shoulders\n\n## What loadr is built on\n\nloadr 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.\n\n### k6\n\nthe modelThe execution model is k6's: the seven executors, open/closed load, the four metric types, thresholds with `abortOnFail`\n\nand exit code 99, checks and groups — and an embedded-JS experience so close the API is import-compatible (`import http from 'k6/http'`\n\n).\n\n### Apache JMeter\n\nthe arsenalJMeter 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`\n\nreads your `.jmx`\n\nplans.\n\n### Gatling\n\nthe DSLGatling gave loadr its flow control — `repeat`\n\n, `while`\n\n, `if`\n\n/`else`\n\nand the random / uniform / round-robin `switch`\n\n— plus feeder strategies (sequential / random / shuffle), JSON feeders, and the request-rate `throttle`\n\n.\n\n### Locust\n\nthe behaviour modelLocust's weighted-task model — users picking `@task(weight)`\n\nactions at random — is exactly loadr's weighted `random`\n\nstep. Its clean real-time UI inspired loadr's management UI, and its master/worker model informed the controller/agent design.\n\nThe 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.\n[Full credits →](/docs/credits.html)\n\nTrademarks 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.\n\nRoadmap\n\n## What's coming\n\nloadr 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.\n\nJust shipped: SQL load testing (PostgreSQL & MySQL), the time-series HTML report, JMESPath & fused check-chains, and the in-UI failure & error breakdown.\n\n### Next up\n\n- Scriptable protocol clients in JS\n\nDrive WebSocket and gRPC from JavaScript, plus`http.batch`\n\nand an async event loop / timers. - Server-side resource monitoring\n\nCorrelate CPU / memory / disk / network of the system-under-test with your load — JMeter's PerfMon, built in. - Programmable load shapes\n\nCompute load per-tick in code, richer injection profiles (`atOnceUsers`\n\n,`nothingFor`\n\n, stepped ramps), and throughput-shaping profiles that adjust concurrency to hold a target RPS.\n\n### Planned\n\n- Proxy recorder\n`loadr record`\n\n— capture real browser/API traffic and generate a test. - Manual pass/fail from JS\n\nMark a response failed/succeeded in script (Locust`catch_response`\n\n-style). - Messaging protocols\n\nKafka, MQTT, JMS and AMQP — likely as plugins on the existing plugin ABI. - Inter-VU coordination & auto-stop\n\nPass data between virtual users at runtime, and stop a run automatically when error-rate or latency guards trip.\n\n### Exploring\n\n- Managed outputs & dashboards\n\nMore exporters and hosted run-over-run trend comparison. - Distributed niceties\n`--expect-workers`\n\ngating and custom controller↔agent messages. - Plugin registry\n\nA browsable catalog of community WASM & native plugins.\n\nWant something prioritised? It probably came from k6, JMeter, Gatling or Locust — tell us which workflow you're missing.\n\nInstall\n\n## Running in under a minute\n\n``` bash\n$ curl -sSL https://github.com/levantar-ai/loadr/releases/latest/download/loadr-x86_64-unknown-linux-gnu.tar.gz | tar xz\n$ sudo mv loadr-*/loadr /usr/local/bin/\n$ loadr version\nbash\n$ cargo install --git \\\n    https://github.com/levantar-ai/loadr loadr-cli\n\n# no system deps: no protoc,\n# no OpenSSL, no JVM, no node\n# macOS (Intel + Apple Silicon), Windows,\n# Linux x86_64 + arm64 — every build, with\n# SHA256 checksums and SLSA provenance:\n# github.com/levantar-ai/loadr/releases\nbash\n$ loadr validate examples/01-quickstart.yaml   # line-numbered diagnostics, did-you-mean fixes\n$ loadr run examples/01-quickstart.yaml        # exit 0 = thresholds passed, 99 = failed\n$ loadr run --ui examples/02-ramping-load.yaml # live dashboard at http://127.0.0.1:6464\n$ loadr report results.json -o report.html     # self-contained HTML report\n```\n\n27 runnable examples ship in the `examples/`\n\nfolder of every download —\nramp, spike and soak tests, data-driven logins, WebSocket chat, gRPC streaming, GraphQL, Redis, SSE,\nheadless-browser timing, raw sockets, environment overlays and a distributed fleet test.\n[Browse all 34 →](/examples/)\n\n## The documentation is exhaustive.\n\nA 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.", "url": "https://wpnews.pro/news/loadr-a-rust-load-testing-tool-that-began-as-a-single-claude-prompt", "canonical_source": "https://loadr.io", "published_at": "2026-06-30 10:05:57+00:00", "updated_at": "2026-06-30 10:21:41.441163+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "large-language-models"], "entities": ["Loadr", "k6", "JMeter", "Gatling", "Locust", "Rust", "Claude"], "alternates": {"html": "https://wpnews.pro/news/loadr-a-rust-load-testing-tool-that-began-as-a-single-claude-prompt", "markdown": "https://wpnews.pro/news/loadr-a-rust-load-testing-tool-that-began-as-a-single-claude-prompt.md", "text": "https://wpnews.pro/news/loadr-a-rust-load-testing-tool-that-began-as-a-single-claude-prompt.txt", "jsonld": "https://wpnews.pro/news/loadr-a-rust-load-testing-tool-that-began-as-a-single-claude-prompt.jsonld"}}