Repository navigation
tropel v0.2.0
Tropel is an open-source load-testing framework in Rust. It runs
Postman collections, HAR files, OpenAPI specs, Bruno and
Insomnia exports, and k6 scripts as load tests — a native Rust hot
path with an embedded QuickJS engine for script execution.
Pre-1.0: the API is unstable. k6 parity is actively expanding and the
tropel-sdksurface still changes between minor versions. Pin an exact
version if you depend on it.
Install
Pick your platform. Linux builds are static musl — they run unmodified in
Alpine, distroless and scratch containers.
# Linux x86_64
curl -fsSL https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-x86_64-unknown-linux-musl.tar.gz | tar xz
sudo install -m755 tropel-v0.2.0-x86_64-unknown-linux-musl/tropel /usr/local/bin/
# Linux arm64
curl -fsSL https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-aarch64-unknown-linux-musl.tar.gz | tar xz
sudo install -m755 tropel-v0.2.0-aarch64-unknown-linux-musl/tropel /usr/local/bin/
# macOS Apple Silicon
curl -fsSL https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-aarch64-apple-darwin.tar.gz | tar xz
sudo install -m755 tropel-v0.2.0-aarch64-apple-darwin/tropel /usr/local/bin/
# macOS Intel
curl -fsSL https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-x86_64-apple-darwin.tar.gz | tar xz
sudo install -m755 tropel-v0.2.0-x86_64-apple-darwin/tropel /usr/local/bin/Windows (PowerShell):
Invoke-WebRequest -Uri "https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-x86_64-pc-windows-msvc.zip" -OutFile tropel.zip
Expand-Archive tropel.zip -DestinationPath .macOS note: binaries are unsigned, so Gatekeeper will quarantine a downloaded
archive. Clear it with xattr -d com.apple.quarantine ./tropel.
Verify your download
curl -fsSLO https://github.com/transithq/tropel/releases/download/v0.2.0/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing # macOS: shasum -a 256 -cFrom source (Rust 1.94+)
cargo build --release # ./target/release/tropelAssets
| asset | contents |
|---|---|
tropel-v0.2.0-<target>.tar.gz / .zip |
tropel, tropel-controller, tropel-agent + LICENSE, README |
tropel-wasm-v0.2.0.tar.gz |
the browser/edge tier — core-wasm, input-wasm, runtime-wasm, shims |
SHA256SUMS |
checksums over every asset above |
Targets: x86_64/aarch64 Linux (musl), x86_64/aarch64 macOS,
x86_64 Windows (MSVC).
Quick start
tropel run collection.json --vus 50 --duration 2m # Postman, HAR, OpenAPI, k6, Bruno, Insomnia
tropel inspect collection.json # preview without sending traffic
tropel extensions # list the input formats this binary shipsFull docs: docs/ — CLI
reference, executors, scripting, metrics, extensions, distributed execution.
What's in it
- Seven executors — constant-vus, ramping-vus, shared/per-vu iterations,
constant & ramping arrival rate, externally-controlled, with graceful
stop/ramp-down, think time and pacing - Postman
pm.*scripting — tests, assertions, variable scopes,
setNextRequest,sendRequest, custom metrics - k6-style scripting —
http.*,check(),group(),sleep(),
Counter/Gauge/Rate/Trend; exportedoptionshonoured - HDR-histogram metrics — p50/p90/p95/p99, sub-timings, tag-scoped
aggregation, thresholds with k6-compatible abort semantics - Streaming outputs — NDJSON, StatsD, InfluxDB, Prometheus, OTLP
(protobuf + gzip), plus stdout/JSON/CSV reporters - Distributed — k6-style execution segments for multi-node runs
- Extensible —
tropel-sdk+tropel build --with <crate>, plus a
sandboxed WASM plugin tier for third-party input formats
npm packages
@tropel/core-wasm@0.2.0 @tropel/input-wasm@0.2.0 @tropel/runtime-wasm@0.2.0 @tropel/shims@0.2.0
Changes in 0.2.0
First tagged release. Versioned 0.2.0 rather than 0.1.0 across all seven
surfaces (binary, tropel-engine, tropel-web, and the four @tropel/* npm
packages — tropel-engine is what --version prints) because
@tropel/shims@0.1.0 and @tropel/runtime-wasm@0.1.0 were published on
2026-08-10 and npm versions are immutable: those artifacts still call the
__tropel_pm_* bridges this tree renamed to __tropel_trp_*, so they cannot
be paired with this runtime. 0.2.0 is the first npm set that matches the
binary.
The API is unstable pre-1.0. k6 parity is actively expanding and the
tropel-sdk surface still moves between minor versions.
Fixed — correctness
sleep()was non-functional on every declarative format (Postman, HAR,
OpenAPI,.http, Insomnia, Bruno).__tropel_native_sleepwas registered as
an async host function on an rquickjsRuntimewith no spawner, so the first
call panicked with "tried to use async function in non async runtime";
rquickjs stashed that panic and re-raised it on whichever VU next threw — a
different VU on a shared runtime. Now a blocking sleep with an absolute
deadline. This also fixesbru.sleep(ms).- Headline
http_req_duration/iteration_durationwere computed from one
metrics shard.shard_for_keyhashed the metric name and its tags,
against its own documented contract, so{url:/a}and{url:/b}landed on
different shards and the merge kept only the largest-count partial. Count,
avg, min, max and p95 were derived from a fraction of the population. http_req_failedwas the maximum of per-shard rates — 10 failures across
400 requests reported0.10instead of0.025. Now merges numerator and
denominator.output_samples_dropped/aggregator_samples_droppedwere multiplied by
SHARD_COUNT— process-global atomics read once per shard and summed, so
one output dropping 1,000 samples reported 4,000.absorb_snapshotdiscarded over-cap series without counting them, so a
controller merge that lost series still reported"unverified": false.- The QuickJS promise-rejection tracker was overwritten by every new VU.
It is a property of the runtime, not the context, so on a shared runtime one
VU's unhandled rejection was recorded into another's map — the first VU
passed silently, the second failed with an error it never raised. bru.setVar/setEnvVar/setCollectionVarwere not inverses of their
getters — they wrote withString(value)while the getters used
JSON.parse, sosetVar('id','1234')read back as the number1234and an
object read back as"[object Object]".@tropel/shimsshipped withoutk6-core.js, leaving every
@tropel/runtime-wasmembedder withoutcheck/group/Counter/Gauge/
Rate/Trend. The npm bundle list is now derived fromShim::ALLin the
Rust source, so the two cannot diverge silently.ws_*samples carriedgroup:"ws"where k6's root group is"".
Changed
- Per-VU JS shims are now selected by input format, and the bytecode cache is keyed by bundle (TR-501). The compiled-shim-bytecode cache was a single
OnceLockkeyed on nothing, so only the full default bundle could use it and every narrowed bundle paid a per-VU source parse+compile — which made shim gating a pessimisation: an http-only script measured 557,824 B/VU against the full bundle's 497,584 B/VU. The cache is now keyed by bundle identity, andShimBundle::for_formatpicks the shim set from the resolvingInputAdapter::id(). ✅MEAS (Apple M2, release, N=25, contexts sharing one worker-threadRuntime): har/openapi/http/insomnia 203,400 B/VU, content-gated http-only 261,878, postman 369,424, k6/unknown format 385,324. (An earlier revision of this entry quoted 280,480 / 336,848 / 479,952 / 497,584 — those came from a harness that summed a shared runtime's heap once per context and divided by N, reporting the whole 25-context total as a per-VU figure. Withdrawn; do not cite them.) Behaviour change: a context created bycreate_vu_js_contextno longer necessarily has all ofpm/chai/_/CryptoJS/bru—bruis dropped for every format exceptbru, and the assertion/utility libraries are dropped for the four formats whose adapters cannot emit a script.pm.jsis still loaded for every format. The k6 Driver's own shim bundle (tropel-input-k6) is unchanged. - License: dual MIT OR Apache-2.0 → Apache-2.0 only.
LICENSE-MITremoved;LICENSE-APACHEnow carries the full canonical text (previously a placeholder stub) and is copied intocrates/tropel-sdk/so published artifacts include it.deny.tomlkeepsMITon the dependency allowlist (third-party crates only).
Full changelog: CHANGELOG.md ·
Issues: github.com/transithq/tropel/issues ·
Licence: Apache-2.0