Examples

34 runnable examples

Every one is a complete, valid test you can run with loadr run <file>. They ship in the examples/ folder of every download, or grab them here.

01-quickstart.yaml
quickstart

The smallest useful loadr test: 10 virtual users hammering one endpoint for 30 seconds, with checks and a pass/fail threshold. loadr run examples/01-quickstart.yaml

02-ramping-load.yaml
ramping-load

Classic ramp test: climb to 50 VUs, hold, ramp down — with think time between requests so VUs behave like humans.

03-arrival-rate.yaml
arrival-rate

Open-model load: start exactly 100 iterations per second regardless of how slowly the target responds. Watch `dropped_iterations` to spot saturation.

04-spike-test.yaml
spike-test

Spike test with a ramping arrival rate: calm baseline, sudden 10x spike, recovery. The abort threshold kills the run if errors explode.

05-data-driven.yaml
data-driven-login

Data-driven login: each iteration takes the next row from users.csv (shared cursor across all VUs, wrapping at EOF).

06-correlation.yaml
correlation

Correlation: extract values from earlier responses (regex, CSS selector, JSONPath, headers, boundary) and reuse them in later requests.

07-scenarios-and-groups.yaml
mixed-workload

Several scenarios running concurrently with independent executors, start times and tags, plus groups and a custom metric.

08-javascript.yaml
javascript-lifecycle

Full JavaScript lifecycle: setup() fetches an auth token once, every iteration runs an exported function, beforeRequest/afterRequest hooks fire around YAML requests, teardown() cleans up.

09-websocket.yaml
websocket

WebSocket load: connect, exchange messages, assert on the conversation.

10-grpc.yaml
grpc

gRPC load: compile .proto files in-process (no protoc needed) or use server reflection, then call unary and streaming methods dynamically.

11-graphql.yaml
graphql

GraphQL over HTTP with variables; GraphQL `errors` are detected and the request is marked failed when no data comes back.

12-tcp-udp.yaml
raw-sockets

Raw socket load: TCP request/response and UDP datagrams, with hex payloads.

13-environments.yaml
environments

One test, many environments: `loadr run -e staging examples/13-environments.yaml` deep-merges the env block over the file. Secrets come from the process environment and are never printed.

14-outputs-and-soak.yaml
soak

Long soak test wired into observability: Prometheus scrape endpoint, JSONL archive, and StatsD — plus an abort threshold as a circuit breaker.

15-distributed.yaml
distributed

Distributed run: submit this to a controller and the load is partitioned across every connected agent (VUs split, arrival rates divided, percentiles merged centrally from HDR histograms — never averaged). loadr controller --bind 0.0.0.0:7625 & loadr agent --join controller-host:7625 --name agent-1 & loadr run --controller controller-host:6464 examples/15-distributed.yaml

16-flow-control.yaml
flow-control

Flow control: repeat, while, if/else and weighted random branches — the control flow from Gatling (repeat/during/doIf/randomSwitch) and the weighted-task model from Locust, in declarative YAML.

17-feeders-and-throttle.yaml
feeders-and-throttle

Feeder strategies (Gatling: sequential / random / shuffle, plus JSON feeders) and a global request-rate ceiling (Gatling throttle / reachRps).

18-sse.yaml
server-sent-events

Server-Sent Events load: open an event stream, read until a condition, assert on the last event.

20-browser.yaml
browser

Real-browser load test: drive headless Chrome over CDP and capture Navigation Timing + Web Vitals (FCP, LCP, DCL, load) for a page. Unlike the protocol-level `http` client, the `browser` protocol renders the page in a real Chrome tab — running JavaScript, fetching subresources, and firing the load/DOMContentLoaded events — so the timings reflect what a user actually experiences. Each VU keeps its own warm tab for the whole run. Requires headless Chrome/Chromium installed on the runner; it is launched lazily on the first browser request.

21-http-advanced.yaml
http-advanced

Advanced HTTP defaults: the "power features" of the HTTP client, all in one test. Exercises: - cache: true per-VU browser-style HTTP cache (fresh hits + ETag/Last-Modified revalidation) - hosts: pin a hostname to a fixed address (curl --resolve) - discard_response_bodies drop bodies after reading them (high throughput) - tracing: true inject a W3C `traceparent` header per request - tls.min_version/max_version pin the negotiated TLS version to 1.2..1.3 Run it, optionally dumping every request/response to the console: loadr run examples/21-http-advanced.yaml loadr run examples/21-http-advanced.yaml --http-debug

22-lifecycle.yaml
lifecycle-hooks

Scenario lifecycle hooks + a custom summary report. Each VU logs in once via the scenario `on_start` hook, runs its `exec` function every iteration, then logs out once via `on_stop` when it retires. After the run, the exported handleSummary(data) function prints a custom end-of-run report instead of the default console summary (k6-compatible).

23-tags.yaml
tag-selection

Tagged scenarios for selective runs. Each scenario carries `tags` (a map of name → value); `loadr run` filters scenarios by their tag *values*. loadr run examples/23-tags.yaml # all four scenarios loadr run --tags smoke examples/23-tags.yaml # only smoke scenarios loadr run --tags read,write examples/23-tags.yaml # read OR write (any-match) loadr run --tags full --exclude-tags write examples/23-tags.yaml # full, but not writes --tags keeps a scenario when it carries at least one of the listed values. --exclude-tags drops a scenario when it carries any of the listed values, and always wins over --tags.

24-timeseries-report.yaml
timeseries-report

Time-series report demo: a ramp-up / spike / ramp-down profile that produces an interesting shape over time. Run it, export the summary, then render the self-contained HTML report — every metric is charted against elapsed time (throughput, latency p50/p95/p99, active VUs, error rate), not just shown as an end-of-run average. loadr run --summary-export results.json examples/24-timeseries-report.yaml loadr report results.json -o report.html open report.html # hover the charts to read off any point in the run The summary JSON carries a top-level `timeline` array (one point per snapshot interval) that drives the charts; the aggregate tables remain exact.

25-check-chains.yaml
check-chains

Fused check-chains: extract → coerce type → transform → validate → save, all in one declarative `extract:` step (Gatling-style). Chains live happily next to the classic `type:`-tagged extractors — mix them freely. Each `chain:` is the variable name to save. Pick exactly one source (jmespath / jsonpath / regex / header / css / xpath / left+right boundary), then optionally `as:` a type, run a `transform:` pipeline, `check:` the value and fall back to a `default:`.

26-failure-breakdown.yaml
failure-breakdown

Deliberately produces a MIX of failures so the web UI's failure breakdown panel has something to group: a healthy endpoint, 4xx and 5xx responses, a check that fails, and a JS step that throws an uncaught exception. Run it with the management UI and watch the "Failure breakdown" panel: docker compose -f examples/harness/docker-compose.yml up -d --build loadr run --ui examples/26-failure-breakdown.yaml (go-httpbin's /status/{code} endpoint returns the requested status code.)

27-postgres.yaml
postgres

PostgreSQL load test, driven by the `loadr-plugin-postgres` native protocol plugin. PostgreSQL support is NOT built into loadr core — it is a runtime-loadable plugin that ships the heavy `sqlx` Rust driver on its own (with ONLY the `postgres` feature, so it carries no `rsa` advisory). The plugin declares the `postgres://`/`postgresql://` URL schemes, so once it is installed a request to one of those URLs routes straight to it; no explicit `protocol:` needed. Each request runs one configured query as the "request"; loadr records query latency in `postgres_req_duration`, the number of rows returned (SELECT) or affected (INSERT/UPDATE/DELETE) in `postgres_rows`, and any database error fails the request (status 1 = ok, status 0 = DB/transport error). Positional parameters are bound safely by the driver with `$1, $2, ...` placeholders. Build + install the plugin, then run: cargo build -p loadr-plugin-postgres --release mkdir -p dist && cp plugins/loadr-plugin-postgres/plugin.toml dist/ \ && cp target/release/libloadr_plugin_postgres.so dist/ loadr plugin install dist loadr run examples/27-postgres.yaml Or point the plan's `plugins:` entry at the built artifact directly (below).

28-mongo.yaml
mongo

MongoDB load test, driven by the `loadr-plugin-mongo` native protocol plugin. MongoDB support is NOT built into loadr core — it is a runtime-loadable plugin that ships the heavy `mongodb` Rust driver on its own. The plugin declares the `mongodb://` (and `mongo://`) URL scheme, so once it is installed a request to a `mongodb://` URL routes straight to it; no explicit `protocol:` is needed. Each request runs one operation (insert/find/update/delete/aggregate/command) from its `plugin:` block. loadr records the operation latency in `mongo_req_duration`, the count of documents inserted/matched/modified/returned in `mongo_docs`, and any driver error fails the request (status 0 = error, status 1 = ok). Build + install the plugin, then run: cargo build -p loadr-plugin-mongo --release mkdir -p dist && cp plugins/loadr-plugin-mongo/plugin.toml dist/ \ && cp target/release/libloadr_plugin_mongo.so dist/ loadr plugin install dist loadr run examples/28-mongo.yaml Or point the plan's `plugins:` entry at the built artifact directly (below).

29-mysql.yaml
mysql

MySQL load test, driven by the `loadr-plugin-mysql` native protocol plugin. MySQL support is NOT built into loadr core — it is a runtime-loadable plugin that ships the heavy `sqlx` Rust driver on its own (with ONLY the `mysql` feature). The plugin declares the `mysql://` URL scheme, so once it is installed a request to such a URL routes straight to it; no explicit `protocol:` is needed. Each request runs one configured query as the "request"; loadr records query latency in `mysql_req_duration`, the number of rows returned (SELECT) or affected (INSERT/UPDATE/DELETE) in `mysql_rows`, and any database error fails the request (status 1 = ok, status 0 = DB/transport error). Positional parameters are bound safely by the driver with `?` placeholders. Build + install the plugin, then run: cargo build -p loadr-plugin-mysql --release mkdir -p dist && cp plugins/loadr-plugin-mysql/plugin.toml dist/ \ && cp target/release/libloadr_plugin_mysql.so dist/ loadr plugin install dist loadr run examples/29-mysql.yaml Or point the plan's `plugins:` entry at the built artifact directly (below).

30-redis.yaml
redis

Redis (RESP) load test, driven by the `loadr-plugin-redis` native protocol plugin. Redis is NOT built into loadr core — it is a runtime-loadable plugin that speaks RESP directly over TCP (no `redis` crate, no OpenSSL). The plugin declares the `redis://` (and `rediss://`) URL scheme, so once it is installed a request to a `redis://` URL routes straight to it; no explicit `protocol:` is needed. Each request runs one command from its `plugin.command` array (argv form). loadr records the command latency in `redis_req_duration` and counts requests in `redis_reqs`. A successful reply is status 0; a RESP error reply is status 1 and fails the request. Build + install the plugin, then run: cargo build -p loadr-plugin-redis --release mkdir -p dist && cp plugins/loadr-plugin-redis/plugin.toml dist/ \ && cp target/release/libloadr_plugin_redis.so dist/ loadr plugin install dist loadr run examples/30-redis.yaml Or point the plan's `plugins:` entry at the built artifact directly (below).

31-kafka.yaml
kafka

Apache Kafka load test, driven by the `loadr-plugin-kafka` native protocol plugin. Kafka support is NOT built into loadr core — it is a runtime-loadable plugin that ships its own Kafka client. That client is `rskafka`, a PURE-RUST client (no librdkafka / C toolchain), so the plugin cross-compiles to every release target. The plugin declares the `kafka://` URL scheme, so once it is installed a request to a `kafka://` URL routes straight to it; no explicit `protocol:` is needed. The broker is the URL authority and the topic is the URL path (`kafka://broker:9092/topic`). Each request runs one operation (produce/fetch) from its `plugin:` block. loadr records the operation latency in `kafka_req_duration`, the count of messages produced/fetched in `kafka_msgs`, and any client error fails the request (status 1 = ok, status 0 = client/transport error). Build + install the plugin, then run: cargo build -p loadr-plugin-kafka --release mkdir -p dist && cp plugins/loadr-plugin-kafka/plugin.toml dist/ \ && cp target/release/libloadr_plugin_kafka.so dist/ loadr plugin install dist loadr run examples/31-kafka.yaml Or point the plan's `plugins:` entry at the built artifact directly (below).

32-rabbitmq.yaml
rabbitmq

RabbitMQ load test, driven by the `loadr-plugin-rabbitmq` native protocol plugin. RabbitMQ support is NOT built into loadr core — it is a runtime-loadable plugin that ships the pure-Rust `lapin` AMQP 0.9.1 client on its own. The plugin declares the `amqp://` / `amqps://` (and `rabbitmq://`) URL schemes, so once it is installed a request to one of those URLs routes straight to it; no explicit `protocol:` is needed. Each request runs one operation (publish/get) from its `plugin:` block. loadr records the operation latency in `rabbitmq_req_duration`, the count of messages published/consumed in `rabbitmq_msgs`, and any broker error fails the request (status 1 = ok, status 0 = AMQP/transport error). Build + install the plugin, then run: cargo build -p loadr-plugin-rabbitmq --release mkdir -p dist && cp plugins/loadr-plugin-rabbitmq/plugin.toml dist/ \ && cp target/release/libloadr_plugin_rabbitmq.so dist/ loadr plugin install dist loadr run examples/32-rabbitmq.yaml Or point the plan's `plugins:` entry at the built artifact directly (below).

33-elasticsearch.yaml
elasticsearch

Elasticsearch load test, driven by the `loadr-plugin-elasticsearch` native protocol plugin. Elasticsearch support is NOT built into loadr core — it is a runtime-loadable plugin. Elasticsearch's API is plain HTTP/JSON, so the plugin talks to it over loadr's own hyper + hyper-rustls stack (pure-Rust TLS, no system OpenSSL); it does not pull in the heavy official `elasticsearch` crate. The plugin declares the `elasticsearch://` (and `es://`) URL schemes — both mapped onto `http://` internally — so once it is installed a request to one of those URLs routes straight to it; no explicit `protocol:` is needed. A plain `http(s)://` URL works too. Each request runs one operation (index/get/search/bulk) from its `plugin:` block. loadr records the operation latency in `elasticsearch_req_duration`, the count of documents written (index = 1, bulk = items succeeded) in `elasticsearch_docs`, and any HTTP/cluster error fails the request (status 1 = ok, status 0 = error). Build + install the plugin, then run: cargo build -p loadr-plugin-elasticsearch --release mkdir -p dist && cp plugins/loadr-plugin-elasticsearch/plugin.toml dist/ \ && cp target/release/libloadr_plugin_elasticsearch.so dist/ loadr plugin install dist loadr run examples/33-elasticsearch.yaml Or point the plan's `plugins:` entry at the built artifact directly (below).

34-c-echo.yaml
c-echo

A protocol plugin written in plain C, loaded over loadr's frozen C ABI. Unlike the Rust native plugins (mongo/redis/...), `c-echo` is a C shared library exporting four `extern "C"` symbols — proving loadr plugins can be authored in non-Rust languages. The host auto-detects the C ABI at load time. It serves the `cecho://` scheme and echoes each request body back, status 200. Build + install the plugin, then run: make -C examples/plugins/c-echo mkdir -p dist && cp examples/plugins/c-echo/plugin.toml dist/ \ && cp examples/plugins/c-echo/libloadr_plugin_cecho.so dist/ loadr plugin install dist loadr run examples/34-c-echo.yaml Or point the plan's `plugins:` entry at the built artifact directly: plugins: - { name: cecho, path: examples/plugins/c-echo/libloadr_plugin_cecho.so }

35-go-echo.yaml
go-echo

A protocol plugin written in Go, loaded over loadr's frozen C ABI. Like the c-echo example, go-echo is NOT a Rust plugin: it's a Go shared library (`go build -buildmode=c-shared`) exporting the four `extern "C"` symbols of loadr's C ABI — proving loadr plugins can be authored in Go. The host auto-detects the C ABI at load time. It serves the `goecho://` scheme and echoes each request body back, status 200. Build + install the plugin, then run: make -C examples/plugins/go-echo mkdir -p dist && cp examples/plugins/go-echo/plugin.toml dist/ \ && cp examples/plugins/go-echo/libloadr_plugin_goecho.so dist/ loadr plugin install dist loadr run examples/35-go-echo.yaml Or point the plan's `plugins:` entry at the built artifact directly: plugins: - { name: goecho, path: examples/plugins/go-echo/libloadr_plugin_goecho.so }