Changelog 6 min read

What's New in loadr

Everything shipped so far, release by release — from the first protocols to the payload generator and the algorithmic-DoS finder.

loadr went from an empty repository to a signed, multi-platform release in a little under 48 hours — the first tagged build, v1.0.0, landed on 14 June 2026. Since then we've shipped twenty-four minor releases on the core line, a separate desktop application, and a plugin catalogue that installs on demand. This is the round-up: what actually shipped, grouped by theme, mapped to the release tags where the mapping is honest. Everything below is in a released build today. Nothing here is a roadmap item.

The foundation (v1.0.0)

The initial release wasn't a skeleton. The engine, executors, metrics and threshold evaluation went in together (da2fe24), and the first tag already spoke a lot of protocols: an HTTP/1.1 and HTTP/2 client with real request-phase timing, WebSocket, dynamically-reflected gRPC, GraphQL, and raw TCP/UDP (57c923f). Scripting came from an embedded QuickJS engine with its own sandboxed standard library (8afa4a2) — QuickJS rather than V8 was a deliberate call: it keeps the binary single-file and the startup cheap.

Outputs were never an afterthought — JSONL, CSV, Prometheus, InfluxDB, OTLP and StatsD exporters all shipped in the first release (f3fe0a2). So did the two importers that make migration real: a JMeter .jmx reader and a k6 script converter (591be61). And the distributed story — a controller/agent architecture over gRPC that merges per-agent HDR histograms rather than averaging summaries — was there from day one (974753b).

JavaScript & flow control

The declarative YAML flow interpreter grew the control structures you actually reach for under load. In one push we added repeat/while/if/random branching, feeder strategies (random, shuffle, JSON) and request throttling (96456d2); shortly after came foreach, switch-by-value, during, retry/tryMax, parallel requests via http.batch, and a rendezvous barrier for coordinated spikes (44f76aa). Scenario lifecycle hooks (on_start/on_stop) and a pile of HTTP power-user knobs — response caching, custom hosts mapping, body discarding, request tracing, TLS-version pinning — landed alongside (a061b2d, bde7646).

Data extraction got a JMESPath source and fused check-chains — extract a value and assert on it in one step (fc5b9d2). SSE, Redis and browser (headless) protocols were wired end-to-end at the same time (5d52912).

Reporting & the web UI

loadr ships a management web UI as a built-in plugin: live dashboards, an in-browser test editor, a fleet view and auth (87d0359). Early releases hardened the reporting side: time-series charts in the standalone HTML report (0eddcb5), a failure-and-error breakdown panel with CSV/report download (f217f9f), and selectable chart styles — line, area or bars (1222dae). A correctness fix worth calling out: live and reported RPS/latency now count all protocols, not just HTTP (dc0d7e5).

Plugins: the install-on-demand catalogue

Plugins are their own release train (plugin-v1.0.0 through plugin-v1.3.0), signed and indexed separately from the CLI so the binary stays small. The model is loadr plugin install <name> against a signed index. Databases were the first movers: SQL split into separate postgres and mysql native protocol plugins (6a0a9be), then mongo (4350f10), then redis, kafka, rabbitmq and elasticsearch as native protocol plugins in one wave (mid-June).

Two things make the system open rather than closed. First, plugins can be WASM (WIT components) or native (abi_stable) libraries. Second, we added a plain C-ABI path so a plugin doesn't have to be written in Rust — the go-echo example is a protocol plugin written in Go (42fa02e, shipped around v1.13.0). By the July catalogue refresh the index carried 29 installable expansion plugins (#70) — everything from datadog, cloudwatch and otlp-metrics to oauth2-minter, jwt-decode, faker-gen, s3-dataset and testcontainers.

Convert & migration

  • JMeter & k6 importers — from v1.0.0 (591be61).
  • HAR recordingsv1.14.0 added loadr convert for HAR with heuristic auto-correlation, so a recorded browser session becomes a parameterised plan instead of a literal replay (#27).
  • Access logs — the workflow wave added nginx/apache combined-format log conversion into a weighted arrival-rate plan, normalising id-like path segments to variables and deriving observed average/peak rates (#71).

Desktop app

The desktop application is an Electron front-end over the bundled CLI, released on its own desktop-v* train (desktop-v1.0.0desktop-v1.2.3) and mirrored across core tags v1.15.0v1.21.0. It was built in milestones: a schema-shaped form composer with two-way Monaco sync (M2, v1.15.0), a drag-and-drop flow builder with a tabbed workspace and import (M3), run plans with live metrics, results, history and compare (M4), a plugins panel to list/install/remove (M5), and a Playwright-for-Electron acceptance suite (M6). The headline feature came in #47: generate a load test with AI from natural language or by pointing it at a repository. A macOS gotcha worth recording — the DMG now bundles a universal2 loadr so Intel users stop hitting EBADARCH (#51).

Packaging & CI integration

  • Homebrew & Scoop — auto-updated formula and manifest generated straight from each release's SHA256SUMS (#46).
  • SLSA provenance — every binary ships checksummed with build provenance (not code-signed; we corrected that claim on the site in #74).
  • JUnit reports + a first-party GitHub Actionv1.22.0 (#48), later extended to Action v2 which runs loadr compare and upserts a single PR comment with the diff table, failing the build on regression (#71).

Observe, compare, sweep, SLO & chaos

The v1.23.0 release added a Prometheus system-metric collector with a timeline overlay — CPU, memory, disk IO and network sampled on the load timeline (#58). The workflow wave that followed (#71, rolling into the v1.25 line) shipped five features that turn loadr into a CI gate:

  • loadr compare <baseline> <current> — per-metric deltas (p50/95/99, error rate, RPS, checks) with regression verdicts, tolerance rules like --max-regression p95=10%, and --assert gating that exits 99 for CI.
  • loadr sweep --var vus=10,50,100 — a parameter-matrix runner that executes every combination and renders a combined comparison matrix.
  • SLO thresholds — SRE-language error budgets that map onto histogram percentiles: http_req_duration: [ "slo(99%) < 300ms" ].
  • observe: [{ type: system }] thresholds evaluated post-run against mid-run samples, e.g. system_cpu: ["max<0.9"].
  • Chaos / fault injection — a per-scenario faults block with latency jitter (uniform/gaussian) and drop_rate, driven by the VU's seeded RNG. A verified drop_rate 0.3 run observed 32.5% http_req_failed and faults_injected=1346.

Payload & complexity testing

The newest capability (#74, 6 July) is a first-class algorithmic-DoS finder. A new crate, loadr-payload, provides 18 adversarial generators — deep nesting, amplification (billion-laughs, YAML bombs), volume, ReDoS, unicode, numeric and hash-collision — each scaled by a single magnitude behind a safety cap. Generate with loadr payload <kind>:n or inline via the ${payload:<kind>:<n>} template, where n can read an env var so a sweep drives it. Then loadr sweep --complexity <axis> --max-exponent K fits response time against input size (log-log least squares), labels the order (linear / super-linear / quadratic), and exits 99 when it breaches the bound. Verified end-to-end: sweeping a nested-markdown payload at Gitea's /api/v1/markup fits O(n^1.6) and fails a --max-exponent 1.2 gate, catching the goldmark super-linear blowup automatically.

How to update

Homebrew:

brew tap levantar-ai/loadr https://github.com/levantar-ai/loadr
brew upgrade loadr

Scoop (Windows):

scoop bucket add loadr https://github.com/levantar-ai/loadr
scoop update loadr

Or grab the checksummed, SLSA-signed binary for your platform straight from loadr.io/download — the desktop app lives on the same page. Run loadr --version to confirm you're on the current line.