Understanding Iterations

An Iteration defines the individual scenario performed during a round. The iteration mode controls how the iteration operates.

Key Attributes of an Iteration

  • Name: Identifier for the iteration.
  • HTTP Request: Configuration for the request, including the method, URL, headers, and payload.
  • Mode: Defines how the iteration operates (see Iteration Modes).
  • Startup Delay: Optional delay in milliseconds before starting the iteration.
  • MaximizeThroughput: Set maximizeThroughput: true to push send-rate as fast as other constraints allow. Maximizing the throughput will result in higher CPU and Memory usage

Structure

  • The plan is at the document root (no plan: key).
  • Rounds are required; each round contains one or more iterations.
  • Each iteration typically contains an httpRequest.

Iteration Features

Iteration Modes

Iteration Modes control the pattern and timing of HTTP requests, offering flexibility to simulate various user behaviors and system loads (see Iteration Modes).

SkipIf

The skipIf property allows conditional execution of an iteration. If the condition evaluates to true, the iteration will be skipped. Conditions can use Flee expressions and may reference session/global variables, placeholders, and metrics.

Example use cases:

  • Skip login attempts if login failed to get a response.
  • Skip requests when a certain error condition has been met.
skipIf: ${LoginResponse.StatusCode} = 401
skipIf: ${LoginResponse.Body.token} = ""
skipIf: ${Metrics.Load.Heavy.Duration.P90ResponseTime} > 250

Before Expressions

The before property runs a list of expressions before the iteration's skipIf and its request(s) — a pre-execution hook for preparing data. Each expression is evaluated in order for its side effects (typically a $find(..., variable=x) that stores a variable); the returned value is discarded.

This closes an ordering gap: skipIf/URL/headers are evaluated before a request is sent, so before lets you set up a variable and then use it in the same iteration/request. before is available at both iteration level (runs once per iteration) and httpRequest level (runs before each request).

before:
  - '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=userId)'
skipIf: ${userId} != 1

See the Before Expressions article and the find method.

After Expressions

The after property runs a list of expressions after the iteration/request executes — a post-execution hook. Like before, each expression is evaluated in order for its side effects (typically a $find(..., variable=x) that stores a variable); the returned value is discarded.

Because it runs after execution, after can read the response and captured variables and prepare data for the next step. It is available at both iteration level (runs once when the iteration completes) and httpRequest level (runs after each request completes). Request-level after runs on both success and failure, but not when skipIf skipped the request or on cancellation.

after:
  - '$find(source=$users.Body, where=item.id > 5, match=count, variable=bigUserCount)'
  - '$greaterthan(a=${bigUserCount}, b=3, variable=hasManyUsers)'

See the before & after Expressions article.

Failure Rules

⚠️ Breaking Change: The old failureCriteria property with individual threshold fields (maxErrorRate, maxP90, maxP50, maxP10, maxAvg, errorStatusCodes) has been permanently removed as of version 3.0.2.6. The last version supporting the old format was 3.0.2.5. Please migrate to the new failureRules format described below.

The failureRules property defines rules that are applied after the iteration finishes. These rules classify the outcome of the iteration as either Failed or Success. This is useful for reporting and post-run analysis.

Each rule can use either:

  • metric: an inline metric expression
  • expression: a Flee boolean expression
  • both together in the same rule

If expression evaluates to true, the rule triggers immediately and independently of metric.

⚠️ Variable scope in expression: Failure rules are evaluated after the iteration finishes, at the run/aggregate level — there is no session context, so placeholders resolve against global variables only. Run‑level metric tokens (${Metrics...}, ErrorRate, SkipRatio, Throughput, TotalTime.*, …) are always available. However, a variable produced by a declarative method ($set, $setvariableif, $find, $counter, etc.) now defaults to session scope and will not be visible here. If you need to fail on such a variable, store it with isGlobal=true (e.g. $find(..., variable=errorCount, isGlobal=true)) so it lands in the global store the rule can see.

failureRules:
  - metric: "ErrorRate > 0.10"
    errorStatusCodes: ">= 500"
  - expression: '${Metrics.CheckoutRound.Pay.Throughput.RPS} < 50'
  - metric: "TotalTime.P90 > 250"
    expression: '${Metrics.CheckoutRound.Pay.ResponseCode.ResponseSummaries[0].Count} > 25'
  - metric: "TotalTime.P50 > 200"
  - metric: "TotalTime.Avg > 180"

CLI Usage

lps --url https://example.com -rc 1000 --failurerule "ErrorRate > 0.05;>= 500" --failurerule "TotalTime.P90 > 250"

Format: "metric[;errorStatusCodes]"

Termination Rules

⚠️ Breaking Change: The old terminationRules format with individual threshold fields (maxErrorRate, maxP90, maxP50, errorStatusCodes) has been permanently removed as of version 3.0.2.6. Please migrate to the new format described below.

The terminationRules property lets you define real-time termination conditions for an iteration. These rules are evaluated continuously by the Master node (aggregating all workers). An iteration will be terminated only if a rule is continuously violated for the entire grace period. For example, with a grace period of 10 seconds, if the violation clears before the 10th second, the test continues without termination.

Each rule can use either:

  • metric: an inline metric expression
  • expression: a Flee boolean expression
  • both together in the same rule

If expression evaluates to true, termination happens immediately and independently of metric or gracePeriod.

⚠️ Variable scope in expression: Termination rules are evaluated continuously by the Master node (aggregating all workers), at the run/aggregate level — there is no session context, so placeholders resolve against global variables only. Run‑level metric tokens (${Metrics...}, ErrorRate, SkipRatio, Throughput, TotalTime.*, …) are always available. However, a variable produced by a declarative method ($set, $setvariableif, $find, $counter, etc.) now defaults to session scope and will not be visible here. If you need to terminate on such a variable, store it with isGlobal=true (e.g. $find(..., variable=errorCount, isGlobal=true)) so it lands in the global store the rule can see.

When metric is used, gracePeriod controls how long the metric condition must stay violated before the iteration is terminated.

terminationRules:
  - metric: "ErrorRate > 0.2"
    errorStatusCodes: ">= 500"
    gracePeriod: "00:00:10"
  - expression: '${Metrics.SearchRound.Results.Throughput.RPS} <= 40'
  - metric: "TotalTime.P90 > 200"
    gracePeriod: "00:00:05"
    expression: '${Metrics.SearchRound.Results.ResponseCode.ResponseSummaries[0].Count} > 50'
  - metric: "TotalTime.P50 > 400"
    gracePeriod: "00:00:15"

CLI Usage

lps --url https://example.com -rc 1000 --terminationrule "ErrorRate > 0.10;00:05:00;>= 500" --terminationrule "TotalTime.P90 > 500;00:00:30"

Format: "metric;gracePeriod[;errorStatusCodes]"

Metric Expression Reference

Both failureRules and terminationRules support expression for general boolean conditions, and metric for inline metric expressions. The metric format below applies to the metric property.

Expression Format

MetricName[.Statistic] Operator Threshold

Supported Metrics

Metric Aliases Statistics Description Example
ErrorRate-(none)Percentage of failed requests"ErrorRate > 0.05"
SkipRatioSkippedRatio, SkippedRequestsRatio(none)Percentage of skipped requests out of total attempted requests"SkipRatio > 0.10"
ThroughputRPS, RequestsPerSecond(none)Requests per second"Throughput < 100"
TotalTime-.P50, .P90, .P95, .P99, .Avg, .Min, .MaxTotal request duration"TotalTime.P90 > 250"
TTFBTimeToFirstByte.P50, .P90, .P95, .P99, .Avg, .Min, .MaxTime to first byte received"TTFB.P90 > 100"
WaitingTimeWaiting.P50, .P90, .P95, .P99, .Avg, .Min, .MaxServer processing time (TTFB - TCP - TLS)"WaitingTime.P90 > 80"
TCPHandshakeTCP.P50, .P90, .P95, .P99, .Avg, .Min, .MaxTCP connection handshake time"TCPHandshake.Avg > 50"
TLSHandshakeTLS, SSL, SSLHandshake.P50, .P90, .P95, .P99, .Avg, .Min, .MaxTLS/SSL handshake time"TLSHandshake.P90 > 100"
SendingTimeSending, Upload, Upstream.P50, .P90, .P95, .P99, .Avg, .Min, .MaxRequest upload time"SendingTime.P90 > 20"
ReceivingTimeReceiving, Download, Downstream.P50, .P90, .P95, .P99, .Avg, .Min, .MaxResponse download time"ReceivingTime.P90 > 50"
ServerTimeServer.P50, .P90, .P95, .P99, .Avg, .Min, .MaxTotal server time from Server-Timing header"ServerTime.P90 > 100"
ServerTimeDBDB, Database.P50, .P90, .P95, .P99, .Avg, .Min, .MaxDatabase time from Server-Timing header"ServerTimeDB.P90 > 50"
ServerTimeCacheCache.P50, .P90, .P95, .P99, .Avg, .Min, .MaxCache time from Server-Timing header"ServerTimeCache.Avg > 10"
ServerTimeAppApp, Application.P50, .P90, .P95, .P99, .Avg, .Min, .MaxApplication time from Server-Timing header"ServerTimeApp.P90 > 80"

SkipRatio formula: skipped / (executed + skipped)

SkippedRequestsCount is also supported as a scalar metric in rule expressions such as "SkippedRequestsCount > 25". It does not support aggregations like .P95.

Note: The ServerTime* metrics require the server to include a Server-Timing HTTP response header with the relevant timing information.

Supported Operators

OperatorDescriptionExample
>Greater than"ErrorRate > 0.05"
>=Greater than or equal"TotalTime.P90 >= 500"
<Less than"Throughput < 100"
<=Less than or equal"TotalTime.Avg <= 200"
=Equal"ErrorRate = 0"
!=Not equal"ErrorRate != 0"
between X and YRange (inclusive)"TotalTime.P90 between 100 and 500"

Error Status Code Filtering

The optional errorStatusCodes property filters which HTTP status codes count as errors when calculating ErrorRate.

ExpressionDescription
">= 500"All 5xx server errors
">= 400"All 4xx and 5xx errors
"< 500"All non-5xx errors (including 4xx)
"between 400 and 499"Only 4xx client errors
"= 429"Only rate limiting errors
"= 0"Connectivity failures only
">= 0"All errors including connectivity failures

Note: Status code 0 represents connectivity failures including DNS resolution failures, connection refused, connection timeout, SSL/TLS handshake failures, and network unreachable errors.

Complete Iteration Example

name: IterationFeaturesPlan # Represents the plan name
rounds:
  - name: FeatureRound
    numberOfClients: 50
    arrivalDelay: 100
    runInParallel: false
    iterations:
      - name: LoginIteration
        httpRequest:
          url: https://httpbin.org/post
          method: POST
          headers:
            Content-Type: application/json
          payload:             
            raw: |
                { "username": "user", "password": "pass" }
      - name: Home
        httpRequest:
          url: https://httpbin.org/
          httpMethod: Get

        # SkipIf (iteration)
        skipIf: ${LoginResponse.StatusCode} = 401

        # Failure Rules (evaluated once the iteration execution is completed)
        failureRules:
          - metric: "ErrorRate > 0.10"
            errorStatusCodes: ">= 400"
          - expression: '${Metrics.FeatureRound.Home.Throughput.RPSCD} < 10'
          - metric: "SkipRatio > 0.15"
          - metric: "TotalTime.P90 > 250"
          - metric: "TotalTime.P50 > 200"
          - metric: "TotalTime.Avg > 180"

        # Termination Rules (evaluated in real-time during execution)
        terminationRules:
          - metric: "ErrorRate > 0.2"
            errorStatusCodes: ">= 400"
            gracePeriod: "00:00:03"
          - expression: '${Metrics.FeatureRound.Home.Throughput.RPS} <= 40'
          - metric: "TotalTime.P90 > 2000"
            gracePeriod: "00:00:05"

Global Iterations and References

Iterations can also be defined as global iterations and referenced later within rounds using the reference property. This allows for reusable iteration configurations across multiple rounds, reducing redundancy and improving maintainability.

name: GlobalIterationPlan
iterations:
- name: GlobalIteration
  mode: DCB
  duration: 300
  batchSize: 100
  coolDownTime: 1000
  httpRequest:
    url: https://httpbin.org/headers
    httpMethod: GET
    httpVersion: 2.0
rounds:
- name: TestRound
  numberOfClients: 1
  reference: ["GlobalIteration"]