Fusillade Documentation
High-performance load testing engine built in Rust
Fusillade is a modern load testing platform that combines the raw performance of Rust with the developer-friendly scripting of JavaScript. Write tests in familiar JS syntax, run them with predictable performance characteristics.
Why Fusillade?
- Rust performance with JavaScript scripting
- Accurate metrics (network time only, no JS overhead)
- Multi-protocol: HTTP/2, WebSocket, gRPC, MQTT, AMQP, SSE
- Browser automation for real user experience testing
- Built-in thresholds for CI/CD pass/fail
Tech Stack
| Runtime | Rust + QuickJS |
| Concurrency | OS Threads |
| HTTP | hyper (HTTP/1.1 & HTTP/2) |
| Histograms | HDR histograms |
No imports needed
All APIs are available as globals. Use local imports only for your own modules.
HTTP & Protocols
http, ws, sse, GrpcClient, JsMqttClient, JsAmqpClient
Testing
check, sleep, print, describe, test, expect
Data
SharedArray, SharedCSV, open, __ENV, __WORKER_ID
Utilities
utils, crypto, encoding, metrics, stats, chromium
Documentation
Getting Started
Installation, first test, shell completion
Configuration
Options, executors, scenarios, thresholds
HTTP API
Requests, responses, cookies, retries
Protocols
WebSocket, gRPC, MQTT, AMQP, SSE
Browser Testing
Chromium automation, real user metrics
Metrics
Built-in metrics, thresholds, exports
Data Loading
CSV, JSON, environment variables
CLI Reference
Commands, flags, TUI, interactive mode
Distributed
Cloud, multi-region, Kubernetes, CI/CD
Advanced
Chaos testing, HAR conversion, memory
Quick Example
# test.js
export const options = {
workers: 10,
duration: '30s',
thresholds: {
'http_req_duration': ['p95 < 500'],
'http_req_failed': ['rate < 0.01'],
}
};
export default function() {
const res = http.get('https://api.example.com/users');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}# Run
$ fusillade run test.jsCommon Patterns
API with Authentication
const users = new SharedCSV('./data/users.csv');
export function setup() {
// Login once, share token with all workers
const res = http.post('https://api.example.com/login', JSON.stringify({
email: 'admin@example.com',
password: __ENV.ADMIN_PASSWORD
}));
return { token: res.json().token };
}
export default function(data) {
http.get('https://api.example.com/protected', {
headers: { Authorization: 'Bearer ' + data.token }
});
}Ramping Load Test
export const options = {
stages: [
{ duration: '1m', target: 10 }, // Ramp up
{ duration: '3m', target: 10 }, // Steady
{ duration: '1m', target: 50 }, // Spike
{ duration: '1m', target: 0 }, // Ramp down
],
thresholds: {
'http_req_duration': ['p95 < 500'],
}
};Multiple User Flows
export const options = {
scenarios: {
browse: {
workers: 50,
duration: '5m',
exec: 'browseProducts',
},
checkout: {
workers: 10,
duration: '5m',
exec: 'checkoutFlow',
},
},
};
export function browseProducts() {
http.get('https://shop.example.com/products');
sleep(2);
}
export function checkoutFlow() {
http.post('https://shop.example.com/cart/add', JSON.stringify({ item: 1 }));
http.post('https://shop.example.com/checkout');
sleep(5);
}CI/CD Integration
$ fusillade run test.js \
--headless \
--abort-on-fail \
--threshold "http_req_duration:p95<500" \
--export-json results.json \
--out junit=results.xmlAPI Quick Reference
| Category | Functions |
|---|---|
| HTTP | http.get() .post() .put() .del() .batch() .cookieJar() |
| WebSocket | ws.connect() socket.send() .recv() .close() |
| Testing | check(res, {...}) sleep(secs) print(msg) |
| Data | new SharedArray() new SharedCSV() open(path) __ENV.VAR |
| Utils | utils.uuid() .randomString() .randomInt() .randomEmail() |
| Crypto | crypto.md5() .sha256() .hmac() |
| Metrics | metrics.histogramAdd() .counterAdd() .gaugeSet() .rateAdd() |
| Browser | chromium.launch() page.goto() .click() .metrics() |