Reference

Reference #

Complete reference for all Loadgen configuration options.


Command-Line Arguments #

loadgen [options]
ArgumentTypeDefaultDescription
-runstringloadgen.dslPath to DSL test file
-configstringloadgen.ymlPath to YAML configuration file
-dint5Test duration in seconds
-cint1Number of concurrent threads
-rint-1 (unlimited)Max requests per second (fixed QPS)
-lint-1 (unlimited)Total request limit
-compressboolfalseCompress request body with gzip
-timeoutint60Request timeout in seconds
-dial-timeoutint3Connection dial timeout in seconds
-read-timeoutint0 (uses -timeout)Read timeout in seconds
-write-timeoutint0 (uses -timeout)Write timeout in seconds
-cpuint-1 (all)Number of CPUs to use
-memint-1 (unlimited)Memory soft limit in MB
-logstringLog level: trace, debug, info, warn, error, off
-debugboolfalseDebug mode — exit immediately on panic with full stack trace
-vboolPrint version info

Environment Variables (env) #

Define default environment variables in YAML or DSL. Command-line environment variables override these at runtime.

YAML format:

env:
  ES_ENDPOINT: http://localhost:9200
  ES_USERNAME: admin
  ES_PASSWORD: admin

DSL format:

# env: {
#   ES_ENDPOINT: "http://localhost:9200",
#   ES_USERNAME: "admin",
#   ES_PASSWORD: "admin",
# },

Usage: $[[env.ES_ENDPOINT]]

IPv6 Support:

Loadgen fully supports IPv6 addresses. Use standard bracket notation ([ipv6addr]:port) in URLs:

env:
  ES_ENDPOINT: "http://[::1]:9200"
  # Or with a real IPv6 address:
  # ES_ENDPOINT: "http://[fd00::1]:9200"
  # Link-local address with zone ID (URL-encoded %25 for %):
  # ES_ENDPOINT: "http://[fe80::18df:9883:1e27:b040%25en0]:9200"

Or from the command line:

ES_ENDPOINT="http://[::1]:9200" loadgen -run loadgen.dsl -d 5 -c 2
# Link-local with zone ID:
ES_ENDPOINT="http://[fe81::18df:9883:1e27:b040%25en0]:9200" loadgen -run loadgen.dsl -d 5 -c 2

Note: For link-local IPv6 addresses with a zone ID (e.g. fe80::1%en0), the % must be URL-encoded as %25 in the URL.


Runner Configuration (runner) #

Global parameters controlling test execution behavior.

ParameterTypeDefaultDescription
total_roundsintunsetNumber of execution rounds. When set, enters round mode; otherwise runs for the specified duration
no_warmboolfalseSkip warmup phase
log_requestsboolfalseLog all request details
log_status_codes[]intOnly log requests with these status codes (e.g. [0, 500])
assert_invalidboolfalseExit with code 1 when assertions fail
assert_errorboolfalseExit with code 2 when request errors occur
reset_contextboolfalseReset context variables between rounds
valid_status_codes_during_warmup[]intStatus codes considered valid during warmup (e.g. [200, 201, 404])
disable_header_names_normalizingboolfalseDisable automatic response header name formatting
default_endpointstringDefault request endpoint; auto-prepended when request line omits host
default_basic_authobjectDefault Basic Auth credentials

DSL format example:

# runner: {
#   total_rounds: 1,
#   no_warm: true,
#   assert_invalid: true,
#   assert_error: true,
#   valid_status_codes_during_warmup: [200, 201],
#   log_status_codes: [0, 500],
#   default_endpoint: "$[[env.ES_ENDPOINT]]",
#   default_basic_auth: {
#     username: "$[[env.ES_USERNAME]]",
#     password: "$[[env.ES_PASSWORD]]",
#   },
# },

Variable Definitions (variables) #

Variables are referenced in requests using $[[variable_name]] and produce a new value on each request.

Variable Types #

TypeDescriptionRequired Parameters
fileRandom line from a text filepath
listRandom item from an inline listdata
sequence32-bit auto-incrementing integer
sequence6464-bit auto-incrementing integer
rangeRandom integer within a rangefrom, to
random_arrayRandom array composed from another variablevariable_key, size
uuidUUID v4 string
now_localCurrent time (local timezone)
now_utcCurrent time (UTC, full format)
now_utc_liteCurrent time (UTC, ISO short format)
now_unixCurrent Unix timestamp
now_with_formatCurrent time (custom format)format

Variable Parameter Details #

file #

{
  name: "ip",
  type: "file",
  path: "dict/ip.txt",
  data: ["10.0.0.1", "10.0.0.2"],
  replace: {
    '"': '\\"',
    '\\': '\\\\',
  },
}
ParameterDescription
pathPath to external text file (one value per line)
dataAdditional values appended after file contents
replaceCharacter replacements applied to the value (for escaping)

NDJSON Corpus Support:

The file variable type also supports NDJSON-formatted corpus files (one complete JSON object per line). This is especially useful for bulk write scenarios — you can use the corpus file directly as the data source for bulk request bodies:

# dict/docs.json (one JSON document per line)
{"title": "Getting Started with Elasticsearch", "author": "alice", "views": 100}
{"title": "Performance Tuning Best Practices", "author": "bob", "views": 350}
{"title": "Cluster Operations Guide", "author": "coco", "views": 220}

Variable definition:

{
  name: "doc",
  type: "file",
  path: "dict/docs.json",
}

Usage in a bulk request:

POST $[[env.ES_ENDPOINT]]/_bulk
{"index": {"_index": "articles", "_id": "$[[uuid]]"}}
$[[doc]]
# request: {
#   body_repeat_times: 1000,
# },

On each repetition, $[[doc]] picks a random line from the corpus file and uses it directly as the document body — no need to manually construct JSON in the DSL. This approach is ideal for:

  • Benchmarking writes with realistic data
  • Bulk-importing existing datasets
  • Maintaining document structure diversity

list #

{
  name: "user",
  type: "list",
  data: ["alice", "bob", "coco"],
}
ParameterDescription
dataString array; one item picked randomly per request

sequence / sequence64 #

{
  name: "id",
  type: "sequence",
  from: 1,
  to: 999999,
}
ParameterDescription
fromStart value (default 0)
toMax value (wraps around when reached)

range #

{
  name: "suffix",
  type: "range",
  from: 10,
  to: 1000,
}
ParameterDescription
fromLower bound
toUpper bound

random_array #

{
  name: "id_list",
  type: "random_array",
  variable_type: "number",
  variable_key: "suffix",
  square_bracket: false,
  string_bracket: "",
  size: 10,
  replace: { ... },
}
ParameterDescription
variable_typeElement type: number or string
variable_keySource variable name
sizeArray length
square_bracketWhether to wrap output with [ ]
string_bracketString to wrap around each element
replaceCharacter replacements on the entire output

now_with_format #

{
  name: "ts",
  type: "now_with_format",
  format: "2006-01-02T15:04:05-0700",
}
ParameterDescription
formatGo time format string ( reference)

Request Configuration (request) #

Each request can be configured via a # request: { ... }, comment block with the following parameters:

ParameterTypeDescription
basic_authobjectPer-request Basic Auth (overrides runner default)
headers[]objectCustom request headers
disable_header_names_normalizingboolDisable automatic request header name formatting
runtime_variablesobjectRequest-level runtime variables (shared within the request)
runtime_body_line_variablesobjectBody line-level variables (independently generated per line pair)
body_repeat_timesintNumber of times to repeat the request body (for bulk construction)

Full example:

POST /_bulk
{"index": {"_index": "demo-$[[suffix]]", "_id": "$[[uuid]]", "routing": "$[[routing_no]]"}}
{"id":"$[[id]]","user":"$[[user]]","batch":"$[[batch_no]]","ts":"$[[ts]]"}
# request: {
#   basic_auth: {
#     username: "$[[env.ES_USERNAME]]",
#     password: "$[[env.ES_PASSWORD]]",
#   },
#   headers: [
#     {Authorization: "Bearer $[[token]]"},
#     {X-Trace-Id: "$[[uuid]]"},
#   ],
#   disable_header_names_normalizing: true,
#   runtime_variables: {
#     batch_no: "uuid",
#   },
#   runtime_body_line_variables: {
#     routing_no: "uuid",
#   },
#   body_repeat_times: 100,
# },

runtime_variables vs runtime_body_line_variables #

TypeWhen GeneratedTypical Use
runtime_variablesOnce per request — the entire request body shares the same valueBatch number, trace ID
runtime_body_line_variablesIndependently per body “line pair” — each pair gets a unique valueRouting key, per-document ID

What’s a “line pair”? For _bulk requests, each document consists of an action line + source line. When body_repeat_times: N replicates the body N times, runtime_body_line_variables ensures each copy gets an independent value, while runtime_variables remains constant across the entire request.

Illustration:

Request body (body_repeat_times: 3):
  Line pair 1: routing_no = aaa   ← runtime_body_line_variables: unique per pair
  Line pair 2: routing_no = bbb
  Line pair 3: routing_no = ccc
  All pairs:   batch_no   = xxx   ← runtime_variables: shared across request

DSL Format vs YAML Format #

Loadgen supports two configuration formats. YAML format parses faster and is recommended for high-throughput scenarios:

YAML format (recommended for benchmarking):

requests:
  - request:
      method: POST
      url: /_bulk
      runtime_variables:
        batch_no: uuid
      runtime_body_line_variables:
        routing_no: uuid
      body_repeat_times: 5000
      body: |
        {"index": {"_index": "medcl", "_type": "_doc", "_id": "$[[uuid]]"}}
        {"id": "$[[id]]", "field1": "$[[list]]", "now_local": "$[[now_local]]", "now_unix": "$[[now_unix]]"}
        {"index": {"_index": "infinilabs", "_type": "_doc", "_id": "$[[uuid]]"}}
        {"id": "$[[id]]", "field1": "$[[list]]", "now_local": "$[[now_local]]", "now_unix": "$[[now_unix]]"}        

The above example has 2 action+source line pairs in the body. With body_repeat_times: 5000, each request sends 10,000 documents. Each line pair’s routing_no is independently generated, while batch_no is shared across the entire request.

Equivalent DSL format:

POST /_bulk
{"index": {"_index": "medcl", "_type": "_doc", "_id": "$[[uuid]]"}}
{"id": "$[[id]]", "field1": "$[[list]]", "now_local": "$[[now_local]]", "now_unix": "$[[now_unix]]"}
{"index": {"_index": "infinilabs", "_type": "_doc", "_id": "$[[uuid]]"}}
{"id": "$[[id]]", "field1": "$[[list]]", "now_local": "$[[now_local]]", "now_unix": "$[[now_unix]]"}
# request: {
#   runtime_variables: {
#     batch_no: "uuid",
#   },
#   runtime_body_line_variables: {
#     routing_no: "uuid",
#   },
#   body_repeat_times: 5000,
# },

Performance tip: YAML format eliminates runtime DSL parsing overhead. In extreme throughput scenarios, you’ll observe higher client send rates with YAML. For functional validation and integration tests, the performance difference is negligible.


Assertions (assert) #

Assertions validate response content. When an assertion fails, remaining requests in the current round are skipped.

Shorthand Format #

# assert: (200, {status: "ok"}),

Equivalent to: status code is 200 AND response body contains {"status": "ok"}.

Standard Format #

# assert: {
#   _ctx.response.status: 200,
#   _ctx.response.body_json.hits.total.value: 1,
# },

Available Context Variables #

PathDescription
_ctx.response.statusHTTP status code
_ctx.response.headerResponse headers
_ctx.response.bodyRaw response body
_ctx.response.body_json.*JSON response fields (supports nested paths)
_ctx.elapsedRequest elapsed time (milliseconds)

Exit Codes #

CodeCondition
0All assertions passed
1Assertion failures exist and runner.assert_invalid: true
2Request errors exist and runner.assert_error: true

Dynamic Variable Registration (register) #

Extract values from responses and register them as variables for subsequent requests.

# register: [
#   { token: "_ctx.response.body_json.access_token" },
#   { task_id: "_ctx.response.body_json.task" },
# ]

After registration, use $[[token]] or $[[task_id]] in later requests.

Typical scenario: login to get a token → use token in subsequent requests.


Warmup Behavior #

By default, Loadgen executes all requests once as a warmup before the actual test:

  • Warmup results are printed to the terminal
  • If warmup fails, you’re prompted whether to continue
  • Set runner.no_warm: true to skip warmup
  • Set runner.valid_status_codes_during_warmup to define which status codes are acceptable during warmup

Output Metrics #

After test completion, Loadgen prints the following:

75 requests finished in 13.261499ms, 139.34MB sent, 0.00bytes received

[Loadgen Client Metrics]
Requests/sec:        14.85           ← Actual client QPS
Request Traffic/sec: 27.58MB         ← Send traffic per second
Total Transfer/sec:  27.58MB         ← Total traffic per second (including response)
Fastest Request:     99.375µs        ← Fastest request
Slowest Request:     1.898458ms      ← Slowest request
Status 0:            75              ← Status code counts

[Latency Metrics]
75 samples of 75 events
Cumulative:  13.261499ms             ← Total elapsed time
HMean:       148.19µs               ← Harmonic mean
Avg.:        176.819µs              ← Arithmetic mean
p50:         146.75µs               ← Median
p75:         168µs                  ← 75th percentile
p95:         202.583µs              ← 95th percentile
p99:         409.458µs              ← 99th percentile
p999:        1.898458ms             ← 99.9th percentile
Long 5%:     690.854µs              ← Slowest 5% average
Short 5%:    106.5µs                ← Fastest 5% average
Max:         1.898458ms
Min:         99.375µs
Range:       1.799083ms
StdDev:      204.268µs
Rate/sec.:   14.85

[Latency Distribution]
          99µs - 279µs ----------    ← Latency distribution histogram
         279µs - 459µs -
         459µs - 639µs -

[Estimated Server Metrics]
Requests/sec:        5655.47         ← Estimated server-side QPS
Avg Req Time:        176.819µs       ← Estimated server processing time
Transfer/sec:        10.26GB         ← Estimated server throughput

Metric Sections #

SectionDescription
Loadgen Client MetricsThroughput and extremes from the client perspective
Latency MetricsDetailed latency distribution with percentiles
Latency DistributionVisual latency histogram
Estimated Server MetricsServer-side estimates (network overhead excluded)

Status Codes and Errors #

  • Status 200: N — Successful responses
  • Status 0: N — Connection failures or timeouts (no HTTP response received)
  • Number of Errors — Total network/connection errors (shown when assert_error is enabled)
  • Number of Invalid — Total assertion failures (shown when assert_invalid is enabled)

Use INFINI Console for monitoring or APM for accurate server-side metrics; client-side statistics are approximations.

Edit Edit this page