Skip to main content

YAML Specification

Root sections

Every valid Relampo YAML script must include these sections at the same top level (root):

  • test (required): test metadata.
  • variables (optional): reusable global variables.
  • data_source (optional): external data input for the test.
  • http_defaults (optional): default HTTP configuration.
  • error_policy (optional): error handling behavior rules.
  • scenarios (required): executable scenarios.

Main structure

test:
name: "My test"
description: "Optional"
version: "1.0"
variables:
base_url: "https://api.example.com"
username: "demo"
data_source:
type: csv
file: "users.csv"
mode: per_vu
http_defaults:
base_url: "{{base_url}}"
headers:
Accept: "application/json"
timeout: "30s"
follow_redirects: true
error_policy:
on_error: stop
on_4xx: continue
on_5xx: stop
scenarios:
- name: "Main"
load:
type: constant
users: 10
duration: 5m
ramp_up: 10s
iterations: 0
steps:
- get: /health

test

test defines script metadata.

Use it like this:

test:
name: "My test"
description: "Optional"
version: "1.0"

Common fields:

  • name (required): test name.
  • description (optional): test description.
  • version (optional): script version.

Notes:

  • name is required to identify the test.

Variables

Variables let you reuse values across the script.

Use this syntax:

{{var}}

Example:

variables:
base_url: "https://api.example.com"

http_defaults:
base_url: "{{base_url}}"

Supported usage:

  • URL
  • headers
  • query params
  • body string
  • body object (string fields)

Notes:

  • If a variable does not exist, it is replaced with an empty string.

Data source

Data sources let you load external data to use in scenarios.

Types:

  • csv
  • txt

Supported configuration:

data_source:
type: csv
file: "/path/users.csv"
mode: per_vu # per_vu | shared | per_worker
strategy: sequential # sequential | random | unique
variable_names: "email,password"
# or bind in header-based mode
bind:
email_col: user_email
pass_col: user_password
on_exhausted: recycle # recycle | stop

Notes:

  • variable_names treats all rows as data (no header).
  • bind uses first row as header.
  • on_exhausted: stop stops that VU when the data source is exhausted.

Fields:

  • mode
    • per_vu (default): each VU keeps its own cursor.
    • shared: all VUs share a global cursor for the same file within a worker.
    • per_worker: picks row by VU index (vu_idx), making row assignment stable per VU.
  • strategy
    • sequential (default): reads next row and advances cursor.
    • random: picks a random row every iteration (no sequential cursor advance).
    • unique: uses a shuffled order without repeating rows until dataset exhaustion.
  • variable_names
    • assigns columns by position (example: email,password).
    • when present, all rows are treated as data (no header).
    • missing columns are filled with empty string.

http_defaults

http_defaults is used to define global, reusable HTTP configuration for a scenario.

It is used to:

  • Avoid repeating base_url, headers, and timeouts on every request.
  • Set default redirect behavior.
  • Control whether embedded resources are fetched and which types are allowed.
  • Exclude embedded resources by pattern (for example analytics or hotjar).

Use it like this:

http_defaults:
base_url: "https://api.example.com"
headers:
User-Agent: "Relampo/1.0"
timeout: "30s"
follow_redirects: true
retrieve_embedded_resources: false
embedded_resource_types: ["js", "css", "img", "font"]
embedded_resource_blacklist: ["analytics", "hotjar"]

Field behavior:

  • timeout: "30s": maximum wait time per request. If exceeded, the request fails with timeout.
  • follow_redirects: true: when true, Relampo follows HTTP redirects (301/302/307/308). When false, it returns the redirect response without following it.
  • retrieve_embedded_resources: false: defines whether Relampo runs only the main request or also fetches embedded resources (js, css, images, fonts). false = main request only; true = main + embedded resources.
  • embedded_resource_types: ["js", "css", "img", "font"]: allowlist of embedded resource types fetched when retrieve_embedded_resources is enabled.
  • embedded_resource_blacklist: ["analytics", "hotjar"]: list of substrings used to skip embedded URLs (case-insensitive match).

error_policy

error_policy defines behavior when request execution hits errors.

It can be defined at root, scenario, or request level.

Use it like this:

scenarios:
- name: "Main"
error_policy:
on_error: stop
on_4xx: continue
on_5xx: stop
on_timeout: stop
steps:
- get: /health
- request:
method: GET
url: /profile
error_policy:
on_4xx: stop

Supported fields:

  • on_error
  • on_4xx
  • on_5xx
  • on_timeout

Supported values:

  • stop
  • continue

Override order:

  • request-level error_policy overrides scenario-level.
  • scenario-level error_policy overrides root-level.

scenarios

scenarios defines executable flows in the test.

Use it like this:

scenarios:
- name: "Main"
load:
type: constant
users: 10
duration: 5m
cookies:
clear_each_iteration: true
policy: standard
cache_manager:
clear_each_iteration: true
max_elements: 1000
steps:
- get: /health

Inside each scenario you can define:

  • load: scenario load pattern.
  • cookies: VU cookie behavior.
  • cache_manager: HTTP cache behavior for requests.
  • error_policy: scenario-level error behavior.
  • steps: action flow executed by the scenario.

scenario.load

scenario.load defines how load is executed for that scenario.

Supported load types:

  • constant
  • ramp
  • ramp_up_down
  • throughput

Common behavior (applies to all 4 types):

  • All types accept duration and iterations.
  • If iterations > 0, each VU runs exactly that number of iterations.
  • If iterations = 0 and duration is set, it loops until duration ends.
  • If neither duration nor iterations is set, it runs once per VU.

constant

Use it like this:

load:
type: constant
users: 10
duration: 5m
ramp_up: 10s
ramp_down: 10s
iterations: 0

Behavior:

  • Empty type is treated as constant.
  • users defines concurrent VUs.

ramp

Use it like this:

load:
type: ramp
start_users: 1
end_users: 50
duration: 10m
iterations: 0

Behavior:

  • If users is missing or <= 1, it uses end_users as total VUs.
  • start_users and end_users are used to describe the linear load profile.

ramp_up_down

Use it like this:

load:
type: ramp_up_down
users: 50
duration: 10m
ramp_up: 2m
ramp_down: 1m
iterations: 0

Behavior:

  • This pattern uses users, duration, ramp_up, and ramp_down.
  • It represents ramp up, steady phase, and ramp down.

throughput

Use it like this:

load:
type: throughput
target_rps: 20
duration: 10m
ramp_up: 1m
ramp_down: 1m
iterations: 0

Behavior:

  • target_rps defines the target requests per second for the whole scenario.
  • Relampo spaces executions to stay close to that RPS target.
  • duration keeps that target active for the configured time window.
  • If iterations > 0, the scenario ends when iterations complete, even if duration remains.
  • ramp_up and ramp_down control ramp-in and ramp-out toward/from the target.

scenario.cookies

scenario.cookies controls how the scenario handles cookies.

Use it like this:

scenarios:
- name: "Main"
cookies:
policy: standard
clear_each_iteration: false
cookies:
- name: session_id
value: abc123
domain: api.example.com
path: /

Behavior:

  • policy supports standard and ignore_cookies.
  • clear_each_iteration: true resets cookie jar on each iteration; false keeps it.
  • cookies[] lets you preload initial cookies (name, value, domain, path).

scenario.cache_manager

scenario.cache_manager enables HTTP response caching in the scenario.

Use it like this:

scenarios:
- name: "Main"
cache_manager: {}
  • With cache_manager active, successful GET requests (status < 400) are cached by full URL.
  • At request level, cache_override can force enabled or disabled, and it overrides scenario-level behavior.

scenario.steps

scenario.steps defines the actions each virtual user executes inside the scenario.

Currently supported step types:

  • HTTP requests: request, get, post, put, delete, patch, head, options
  • Flow control: if, loop, retry
  • Organization and measurement: group
  • Validation: assertions
  • Pauses: think_time

Execution behavior:

  • steps run in order, top to bottom.
  • If a step contains nested steps, that block runs first, then flow continues.

step.request

step.request defines an HTTP call inside the flow.

1. When to use short vs long form

  • Use short form (get, post, put, delete, patch, head, options) when you only need a simple call.
  • Use long form (request) when you need details like headers, body, assertions, extractors, timeout, files, or error_policy.

2. Minimal request

steps:
- request:
method: GET
url: /health

3. What it inherits and overrides

  • It inherits from http_defaults (for example base_url, headers, and timeout).
  • Values declared inside the request override global defaults.

4. step.request subsections

The following blocks are part of step.request and are documented as separate quick-reference sections.

step.request.headers

headers defines request-specific HTTP headers.

Use it like this:

- request:
method: GET
url: /me
headers:
Authorization: "Bearer {{token}}"
Accept: "application/json"

Behavior:

  • It is a key: value object.
  • Values are interpolated with variables.
  • If a header also exists in http_defaults.headers, request-level value overrides it.

step.request.query_params

query_params adds parameters to the final request query string.

Use it like this:

- request:
method: GET
url: /search
query_params:
q: "relampo"
page: "1"

Behavior:

  • It is a key: value object.
  • Values are interpolated with variables.
  • They are applied on top of the resolved request URL.

step.request.body

body defines the request HTTP payload.

Use it like this:

- request:
method: POST
url: /login
body:
user: "{{username}}"
pass: "{{password}}"

Supported types and behavior:

  • string: sent as literal string (interpolated).
  • object: serialized as JSON; string fields are interpolated.
  • Other types: JSON marshaling is attempted.
  • If Content-Type is not set and body is serialized as JSON, Relampo sets application/json.

step.request.timeout

timeout sets a request-specific timeout.

Use it like this:

- request:
method: GET
url: /reports
timeout: "45s"

Behavior:

  • Uses duration format (500ms, 5s, 1m).
  • If invalid, it falls back to client/global timeout.

step.request.enabled

enabled lets you turn a request on/off.

Use it like this:

- request:
method: GET
url: /experimental
enabled: false

Behavior:

  • false: request is skipped.
  • true or missing: request executes normally.

step.request.assertions

Inside step.request, validations can be defined in two formats: assert and assertions.

Use them like this:

- request:
method: GET
url: /health
assert:
status: 200
body_contains: "ok"
- request:
method: GET
url: /health
assertions:
- type: status
value: 200
- type: contains
value: "ok"

Supported types and behavior:

  • assert (object format): direct keys such as status, status_in, body_contains, body_not_contains, body_matches, response_time_ms, jsonpath, json, header, response_size.
  • assertions (list): supports status, contains, not_contains, regex, jsonpath, json, header, response_time, response_time_max, response_size.

Assertion types (in assertions):

  • status: validates expected HTTP status code.
  • contains / not_contains: validates presence or absence of text in response body.
  • regex: validates response body with a regular expression.
  • jsonpath / json: validates a JSON value by path.
  • header: validates a response header value.
  • response_time / response_time_max: validates response time.
  • response_size: validates response size.

step.request.extractors

Inside step.request, extractors can be defined in two formats: extract and extractors.

Use them like this:

- request:
method: POST
url: /login
extract:
token: "jsonpath($.token)"
req_id: "header.X-Request-Id"
- request:
method: POST
url: /login
extractors:
- type: jsonpath
var: token
expression: $.token
default: ""
- type: regex
var: order_id
pattern: "orderId=(\\w+)"
capture_mode: first

Supported types and behavior:

  • extract (simple object format): supports body, header.<Name>, regex("..."), jsonpath(...).
  • extractors (list): supports header, body, jsonpath (alias json), xpath, boundary, regex.

Extractor types (in extractors):

  • regex: extracts values with a regular expression from body, headers, or status_line depending on from.
  • jsonpath / json: extracts values from JSON responses using expression or path.
  • header: extracts the value of a specific response header.
  • xpath: extracts values from XML/HTML responses using XPath.
  • boundary: extracts text between left_boundary and right_boundary.

Behavior options:

  • from supports body, headers, status_line.
  • capture_mode supports first, all, index, random.
  • default lets you assign a fallback value when no match is found.

step.request.files

files enables multipart uploads.

Use it like this:

- request:
method: POST
url: /upload
body:
category: invoices
files:
- field: file
path: /tmp/invoice.pdf
mime: application/pdf

Supported types and behavior:

  • Each file entry uses field, path, and optional mime.
  • If files is present, request is sent as multipart/form-data.

step.request.error_policy

error_policy sets error behavior only for that request.

Use it like this:

- request:
method: GET
url: /profile
error_policy:
on_error: stop
on_4xx: continue
on_5xx: stop
on_timeout: stop

Supported values and behavior:

  • Supported values: stop and continue.
  • Can define on_error, on_4xx, on_5xx, on_timeout.
  • At request level, it overrides scenario.error_policy.

step.request.cache_override

cache_override lets a request override scenario-level cache behavior.

Use it like this:

- request:
method: GET
url: /catalog
cache_override: enabled

Supported values:

  • Supported modes: inherit, enabled, disabled.
  • cache_override controls request-level HTTP cache behavior.

step.request.cookie_override

cookie_override lets a request override scenario-level cookie behavior.

Use it like this:

- request:
method: GET
url: /catalog
cookie_override: disabled

Supported values:

  • Supported modes: inherit, enabled, disabled.
  • cookie_override controls whether the request uses cookie jar.

step.request.redirects

follow_redirects and redirect_automatically control redirects at request level.

Use it like this:

- request:
method: GET
url: /old-path
follow_redirects: false

Behavior:

  • Both are booleans.
  • Precedence: redirect_automatically > follow_redirects > http_defaults.follow_redirects.
  • If effective value is false, Relampo does not follow redirects and returns the 3xx response.

step.request.retrieve_embedded_resources

retrieve_embedded_resources enables/disables embedded resource fetching for that request.

Use it like this:

- request:
method: GET
url: /home
retrieve_embedded_resources: true

Behavior:

  • Boolean at request level.
  • Evaluated only for successful GET responses (status < 400) with HTML/CSS content.
  • Uses resource types and blacklist from http_defaults.

step.request.spark

spark runs JavaScript scripts before or after request execution.

Use it like this:

- request:
method: GET
url: /profile
spark:
- when: before
script: |
vars.set("trace_id", "abc-123")
- when: after
script: |
if (response.status === 200) {
vars.set("ok", true)
}

Supported values and behavior:

  • when supports before and after (defaults to after when omitted).
  • script accepts JavaScript.
  • Primary goal: transform values and generate dynamic variables for subsequent steps.
  • Available context: vars.get, vars.set, log.
  • response exists only in after (status, body, latency_ms).

Example (split a value and store a variable):

- request:
method: POST
url: /login
spark:
- when: after
script: |
var payload = JSON.parse(response.body || "{}");
var session = String(payload.session_id || "");
var parts = session.split("-");
vars.set("session_prefix", parts[0] || "");

Example (normalize response data into a reusable variable):

- request:
method: GET
url: /profile
spark:
- when: after
script: |
var payload = JSON.parse(response.body || "{}");
var user = payload.user || {};
var email = String(user.email || "");
if (email) {
vars.set("email_lower", email.toLowerCase());
}

step.control_flow

step.control_flow controls branching, repetition, and retries inside steps.

Currently supported control flow steps:

  • if
  • loop
  • retry

Example:

steps:
- if: "{{token}} != ''"
steps:
- get: /profile
- loop:
count: 3
break_on: "{{done}} == true"
steps:
- get: /poll
- retry:
attempts: 3
backoff: exponential
initial_delay: 1s
max_delay: 10s
multiplier: 2
steps:
- get: /health

Behavior:

  • if runs nested steps only when the condition evaluates to true.
  • loop repeats nested steps based on count (or until break_on is true).
  • retry reruns nested steps until success or attempts are exhausted.

Common fields:

  • if: condition + steps.
  • loop: count, break_on, steps.
  • retry: attempts, backoff, initial_delay, max_delay, multiplier, steps.

step.group

step.group groups related steps under a named block.

Use it like this:

steps:
- group:
name: "Login Flow"
steps:
- post: /login
- get: /profile

step.assertions

step.assertions validates the most recent response inside the flow.

Example:

steps:
- get: /health
- assertions:
- type: status
value: 200
- type: contains
value: "ok"
- type: response_time
value: "<800"

Behavior:

  • It always evaluates against the immediately previous response.
  • If there is no previous response, the step fails.

Supported assertion types:

  • status: validates that the HTTP status code exactly matches the expected value (for example 200).
  • contains / not_contains: validates whether response body includes or excludes text.
  • regex: validates response body with a regular expression.
  • jsonpath / json: validates existence or value at a JSON path (for example $.data.id).
  • header: validates that a header exists or has a specific value.
  • response_time / response_time_max: validates response time with comparisons like <800 or >200.
  • response_size: validates response body size.

step.think_time

step.think_time adds a pause between actions to simulate real user timing.

Supported types:

  • fixed: fixed pause with duration (or short form think_time: 2s).
  • uniform: uniform random pause between min and max.
  • normal: normal random pause using mean and std_dev (clamped by min/max when provided).
steps:
- get: /health
- think_time: 2s
steps:
- think_time:
min: 1s
max: 3s
distribution: uniform
steps:
- think_time:
mean: 2s
std_dev: 500ms
min: 1s
max: 4s
distribution: normal

Behavior:

  • If you use duration (or short form think_time: 2s), that value takes precedence.
  • If duration is missing, it uses min/max range (uniform distribution by default).
  • If distribution: normal, it uses mean and std_dev, then clamps by min/max when provided.
  • If no valid time values are provided, no pause is applied.

Common fields:

  • duration: fixed pause.
  • min / max: pause range.
  • distribution: uniform or normal.
  • mean / std_dev: used for normal distribution.

scenarios is required and must include at least one scenario.