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

RuntimeRust + QuickJS
ConcurrencyOS Threads
HTTPhyper (HTTP/1.1 & HTTP/2)
HistogramsHDR 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

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.js

Common 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.xml

API Quick Reference

CategoryFunctions
HTTPhttp.get() .post() .put() .del() .batch() .cookieJar()
WebSocketws.connect() socket.send() .recv() .close()
Testingcheck(res, {...}) sleep(secs) print(msg)
Datanew SharedArray() new SharedCSV() open(path) __ENV.VAR
Utilsutils.uuid() .randomString() .randomInt() .randomEmail()
Cryptocrypto.md5() .sha256() .hmac()
Metricsmetrics.histogramAdd() .counterAdd() .gaugeSet() .rateAdd()
Browserchromium.launch() page.goto() .click() .metrics()