Configuration
Configure tests via script options, config files, or CLI flags
Configuration Options
Configure via export const options in your script.
| option | type | description | example |
|---|---|---|---|
| workers | number | Concurrent workers | 10 |
| duration | string | Test duration. Supports fractional values. | "30s", "1.5m", "0.5h" |
| stages | array | Ramping schedule | [{duration: "10s", target: 50}] |
| thresholds | object | Pass/fail criteria for CI/CD | {"http_req_duration": ["p95 < 500"]} |
| iterations | number | Fixed iterations per worker (then exit) | 10 |
| warmup | string | URL for connection pool warmup | "https://api.example.com" |
| stop | string | Wait time for active iterations (default: 30s) | "30s" |
| stack_size | number | Worker thread stack (bytes, default 32KB) | 65536 |
| heap_size | number | JS engine heap size limit per worker in bytes. Default: 262144 (256KB). Increase if scripts use large data structures. | 524288 |
| min_iteration_duration | string | Minimum iteration time (rate limiting) | "1s" |
| jitter | string | Add artificial latency (chaos) | "500ms" |
| drop | number | Drop probability 0.0-1.0 (chaos) | 0.05 |
| response_sink | boolean | Discard response bodies to save memory | true |
| abort_on_fail | boolean | Abort immediately if threshold breached | true |
| no_endpoint_tracking | boolean | Disable per-URL metrics (reduce memory) | true |
| memory_safe | boolean | Throttle workers on high memory usage | true |
| insecure | boolean | Skip TLS certificate verification | true |
| max_redirects | number | Max HTTP redirects (0 to disable) | 5 |
| user_agent | string | Default User-Agent header | "MyApp/1.0" |
| scenarios | object | Multiple 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 iterationsshared-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 workersdropped_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.tsBasic 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