Configuration

Configure tests via script options, config files, or CLI flags

Configuration Options

Configure via export const options in your script.

optiontypedescriptionexample
workersnumberConcurrent workers10
durationstringTest duration. Supports fractional values."30s", "1.5m", "0.5h"
stagesarrayRamping schedule[{duration: "10s", target: 50}]
thresholdsobjectPass/fail criteria for CI/CD{"http_req_duration": ["p95 < 500"]}
iterationsnumberFixed iterations per worker (then exit)10
warmupstringURL for connection pool warmup"https://api.example.com"
stopstringWait time for active iterations (default: 30s)"30s"
stack_sizenumberWorker thread stack (bytes, default 32KB)65536
heap_sizenumberJS engine heap size limit per worker in bytes. Default: 262144 (256KB). Increase if scripts use large data structures.524288
min_iteration_durationstringMinimum iteration time (rate limiting)"1s"
jitterstringAdd artificial latency (chaos)"500ms"
dropnumberDrop probability 0.0-1.0 (chaos)0.05
response_sinkbooleanDiscard response bodies to save memorytrue
abort_on_failbooleanAbort immediately if threshold breachedtrue
no_endpoint_trackingbooleanDisable per-URL metrics (reduce memory)true
memory_safebooleanThrottle workers on high memory usagetrue
insecurebooleanSkip TLS certificate verificationtrue
max_redirectsnumberMax HTTP redirects (0 to disable)5
user_agentstringDefault User-Agent header"MyApp/1.0"
scenariosobjectMultiple named scenarios{browse: {...}}

Duration strings accept ms, s, m, h suffixes with fractional values: "500ms", "1.5s", "0.5m". A plain number is treated as milliseconds.

Threshold Syntax

p95 < 500 - 95th percentile under 500ms

p99 < 1000 - 99th percentile under 1000ms

avg < 200 - Average under 200ms

rate < 0.01 - Rate under 1% (for error rates)

count > 100 - Count greater than 100

Note: Spaces around operators are required.

Config Aliases

Alternative option names are supported (both work):

stages = schedule

thresholds = criteria

timeUnit = time_unit

responseSink = response_sink

startTime = start_time

maxRedirects = max_redirects

userAgent = user_agent

noEndpointTracking = no_endpoint_tracking

abortOnFail = abort_on_fail

memorySafe = memory_safe

minIterationDuration = min_iteration_duration

Test Types

Different load testing strategies for different goals.

Load Test (Ramping)

Gradually increase load to find performance characteristics.

stages: [
  { duration: "1m", target: 10 },
  { duration: "3m", target: 10 },
  { duration: "1m", target: 50 },
  { duration: "1m", target: 0 }
]

Stress Test

Push beyond normal capacity to find the breaking point.

stages: [
  { duration: "2m", target: 100 },
  { duration: "5m", target: 200 },
  { duration: "2m", target: 0 }
]

Soak Test (Endurance)

Run at moderate load for extended periods to detect memory leaks.

workers: 50,
duration: "4h"

Spike Test

Sudden traffic bursts to test auto-scaling.

stages: [
  { duration: "10s", target: 10 },
  { duration: "1s", target: 500 },
  { duration: "30s", target: 500 },
  { duration: "1s", target: 10 }
]

Executor Types

Control how workers are scheduled.

constant-workers (default)

Fixed number of workers for the entire duration.

export const options = {
  executor: 'constant-workers',
  workers: 10,
  duration: '30s'
};

ramping-workers

Variable workers that ramp up/down according to stages.

export const options = {
  executor: 'ramping-workers',
  stages: [
    { duration: '1m', target: 10 },
    { duration: '3m', target: 50 },
    { duration: '1m', target: 0 }
  ]
};

constant-arrival-rate

Fixed request rate regardless of response times.

export const options = {
  executor: 'constant-arrival-rate',
  rate: 100,
  timeUnit: '1s',
  duration: '1m',
  workers: 50
};

ramping-arrival-rate

Variable request rate through stages - ideal for API rate testing.

export const options = {
  executor: 'ramping-arrival-rate',
  stages: [
    { duration: '30s', target: 50 },   // Ramp to 50 RPS
    { duration: '1m', target: 200 },   // Ramp to 200 RPS
    { duration: '30s', target: 0 },    // Ramp down
  ],
  workers: 50,  // Worker pool to sustain rate
};

per-worker-iterations

Each worker runs a fixed number of iterations then exits.

export const options = {
  executor: 'per-worker-iterations',
  workers: 10,
  iterations: 20,
  maxDuration: '5m'
};
// Total: 10 workers x 20 iterations = 200 iterations

shared-iterations

Fixed total iterations shared across all workers.

export const options = {
  executor: 'shared-iterations',
  workers: 10,
  iterations: 100,
  maxDuration: '5m'
};
// Total: exactly 100 iterations distributed across 10 workers
Note: For arrival rate executors, workers act as a pool that picks up iteration requests. The engine spawns iterations at the target rate, and available workers execute them. If all workers are busy, iterations are dropped (tracked as dropped_iterations metric).

Multiple Scenarios

Run multiple user types concurrently with independent configurations.

export const options = {
  scenarios: {
    browse: {
      workers: 10,
      duration: '30s',
      exec: 'browseProducts',
    },
    checkout: {
      workers: 5,
      duration: '1m',
      exec: 'checkoutFlow',
      startTime: '30s',  // starts after 30s delay
    },
  },
};

export function browseProducts() {
  http.get('https://api.example.com/products');
  sleep(1);
}

export function checkoutFlow() {
  http.post('https://api.example.com/checkout', JSON.stringify({item: 1}));
  sleep(2);
}

TypeScript Support

Fusillade natively supports TypeScript (.ts and .mts files). Scripts are automatically transpiled before execution using the OxC compiler — no build step, tsconfig, or npm packages needed.

Getting Started with TypeScript

# Initialize a TypeScript project

$ fusillade init -t -o my-test.ts --config
# Creates my-test.ts with typed options and a fusillade.yaml config file

# Run a TypeScript test

$ fusillade run test.ts
$ fusillade run test.ts -w 50 -d 2m   # Override options via CLI

# Validate without running

$ fusillade validate test.ts

Basic Example

# test.ts

interface Options {
  workers: number;
  duration: string;
  thresholds: Record<string, string[]>;
}

export const options: Options = {
  workers: 20,
  duration: '1m',
  thresholds: {
    'http_req_duration': ['p95 < 500'],
    'http_req_failed': ['rate < 0.01'],
  },
};

export default function(): void {
  const res = http.get('https://api.example.com/health');

  check(res, {
    'status is 200': (r: any) => r.status === 200,
  });

  sleep(1);
}

Supported TypeScript Features

Type annotations - variables, parameters, return types

Interfaces - stripped at transpilation

Type aliases - type Foo = string | number

Generics - function identity<T>(x: T): T

Enums - const enums and regular enums

Access modifiers - public, private, protected, readonly

Type assertions - value as Type

Tuple types - [string, number]

Utility types - Record, Partial, Pick, Omit, etc.

Async/await - with Promise<T> return types

Optional chaining - obj?.prop with type info

Generics and Advanced Types

# typed-api-test.ts

interface ApiResponse<T> {
  status: number;
  data: T;
}

interface User {
  id: number;
  name: string;
  email: string;
}

function parseResponse<T>(res: any): ApiResponse<T> {
  return {
    status: res.status,
    data: JSON.parse(res.body) as T,
  };
}

export const options = {
  workers: 10,
  duration: '30s',
};

export default function(): void {
  const res = http.get('https://api.example.com/users/1');
  const parsed = parseResponse<User>(res);

  check(res, {
    'status is 200': () => parsed.status === 200,
    'has valid user': () => parsed.data.id > 0,
    'has email': () => parsed.data.email.includes('@'),
  });
}

TypeScript Imports

Local .ts imports work seamlessly. Organize shared utilities in separate files:

# support/helpers.ts

export function getAuthHeaders(token: string): Record<string, string> {
  return { Authorization: `Bearer ${token}` };
}

export function randomEmail(): string {
  return `user_${Math.random().toString(36).slice(2)}@test.com`;
}

export interface TestConfig {
  baseUrl: string;
  authToken: string;
}

# test.ts

import { getAuthHeaders, randomEmail, TestConfig } from './support/helpers.ts';

const config: TestConfig = {
  baseUrl: 'https://api.example.com',
  authToken: __ENV.API_TOKEN || 'test-token',
};

export default function(): void {
  const headers = getAuthHeaders(config.authToken);
  http.post(`${config.baseUrl}/users`, JSON.stringify({
    email: randomEmail(),
  }), { headers });
}

Lifecycle Hooks with TypeScript

# lifecycle-test.ts

interface SetupData {
  token: string;
  userId: number;
}

export function setup(): SetupData {
  const res = http.post('https://api.example.com/login', JSON.stringify({
    email: 'test@example.com',
    password: 'secret',
  }));
  const body = JSON.parse(res.body);
  return { token: body.token, userId: body.user_id };
}

export default function(data: SetupData): void {
  http.get('https://api.example.com/profile', {
    headers: { Authorization: `Bearer ${data.token}` },
  });
}

export function teardown(data: SetupData): void {
  http.post('https://api.example.com/logout', null, {
    headers: { Authorization: `Bearer ${data.token}` },
  });
}

File Extensions

.ts - Standard TypeScript module

.mts - ES module TypeScript

.js - JavaScript (pass-through, no transpilation)

How it works: Fusillade uses OxC for zero-overhead type stripping. Types are syntactically removed before the JavaScript engine executes. There is no type checking at runtime — types exist purely for developer experience.

Type checking: For type safety, use your editor (VS Code provides automatic type checking) or run tsc --noEmit before executing your test.

Dashboard: TypeScript files (.ts, .mts) can be uploaded directly in the dashboard when creating a test. The cloud workers handle transpilation automatically.

Lifecycle Hooks

Optional functions that run once before and after the test.

export function setup() {
  // Runs once before test starts
  const res = http.post('https://api.example.com/login', JSON.stringify({
    username: 'testuser', password: 'secret'
  }));
  return { authToken: JSON.parse(res.body).token };
}

export default function(data) {
  // Each worker receives setup data
  http.get('https://api.example.com/profile', {
    headers: { Authorization: 'Bearer ' + data.authToken }
  });
}

export function teardown(data) {
  // Cleanup after all workers finish
  http.post('https://api.example.com/logout', null, {
    headers: { Authorization: 'Bearer ' + data.authToken }
  });
}

export function handleSummary(data) {
  // Custom report generation
  return {
    'summary.json': JSON.stringify(data, null, 2)
  };
}

Configuration Files

External YAML or JSON configuration files.

# Usage

$ fusillade run script.js --config config/stress-test.yaml
$ fusillade run script.js --config config/stress-test.yaml --workers 100  # CLI overrides

# config/ramping.yaml

schedule:
  - duration: 30s
    target: 10
  - duration: 1m
    target: 50
  - duration: 30s
    target: 0

criteria:
  http_req_duration:
    - p95<500
  http_req_failed:
    - rate<0.01

insecure: false
max_redirects: 10