Skip to content

JMeter Logic Controllers and Flow Control Guide

Master JMeter flow control: If, While, Loop, ForEach, Switch, and Transaction Controllers with Groovy condition syntax and transaction metrics.

Difficulty
intermediate
Guide type
how-to
Estimated read time
13 min read
Last verified version
Verified JMeter 5.6

JMeter Logic Controllers and Flow Control Guide

Section titled “JMeter Logic Controllers and Flow Control Guide”

Logic Controllers determine the order and conditions under which samplers in a test plan execute. They allow you to build realistic, branching, looping, and aggregated user flows—such as conditional checkouts, polling asynchronous tasks, looping through array responses, and calculating composite business transaction metrics.

This guide provides a practical reference to the most critical logic controllers, condition syntax, and common orchestration patterns.


ControllerPurposeTypical Scenario
Transaction ControllerAggregates child samplers into one composite transaction metricMeasuring total checkout duration (3 API calls as 1 business transaction)
If ControllerExecutes child elements only if a condition evaluates to trueConditional paths (e.g., execute payment only if balance > 0)
While ControllerLoops child elements until a condition evaluates to falsePolling an asynchronous order or job status endpoint until STATUS == READY
ForEach ControllerIterates over an array of indexed JMeter variables (item_1, item_2)Processing every item extracted by a JSON or RegEx extractor
Loop ControllerExecutes children a fixed number of timesRepeating a specific step within a thread iteration
Switch ControllerSwitches execution to one child based on a numeric index or nameMulti-branch routing based on user type (ADMIN, CUSTOMER, GUEST)
Once Only ControllerExecutes only during the first iteration of each threadLogin or token retrieval at thread startup
Runtime ControllerLimits execution of child elements to a specified number of secondsTime-boxing a specific test phase

2. If Controller & Modern Groovy Conditions

Section titled “2. If Controller & Modern Groovy Conditions”

The If Controller controls conditional branching.

// Check string equality
\${__groovy(vars.get("userType") == "PREMIUM")}
// Check HTTP response code from previous request
\${__groovy(vars.get("JMeterThread.last_sample_ok") == "true")}
// Check numeric value
\${__groovy(vars.get("cartTotal").toInteger() > 100)}
// Check variable existence / not empty
\${__groovy(vars.get("authToken") != null && !vars.get("authToken").isEmpty())}
  • Evaluate for all children: If checked, JMeter re-evaluates the condition before executing every child element. If unchecked, it evaluates the condition once upon entering the controller.

3. While Controller (Async Polling & Retries)

Section titled “3. While Controller (Async Polling & Retries)”

The While Controller loops until its condition evaluates to false.

  • Blank (empty): Exits when the last sampler in the loop fails.
  • LAST: Exits when the last sampler fails. If the sampler before the loop failed, the loop is not entered.
  • Groovy Expression: Custom condition string evaluating to "false" or "true".

Pattern: Polling Asynchronous Status with Max Retries

Section titled “Pattern: Polling Asynchronous Status with Max Retries”

To poll an endpoint /api/jobs/\${jobId}/status until status is COMPLETED (with a max retry safety counter):

  1. Before While Controller (JSR223 Sampler):
vars.put("jobStatus", "PENDING")
vars.put("pollCount", "0")
  1. While Controller Condition:
\${__groovy(vars.get("jobStatus") != "COMPLETED" && vars.get("pollCount").toInteger() < 10)}
  1. Inside While Controller:
    • HTTP Request: GET /api/jobs/\${jobId}/status
    • JSON Extractor: extracts jobStatus
    • Flow Control Action: 2-second think time
    • JSR223 PostProcessor:
int count = vars.get("pollCount").toInteger() + 1
vars.put("pollCount", count.toString())

4. ForEach Controller (Iterating Over Extracted Arrays)

Section titled “4. ForEach Controller (Iterating Over Extracted Arrays)”

When a JSON Extractor extracts an array with match number -1 (all matches), JMeter generates indexed variables:

  • productId_matchNr = 3
  • productId_1 = prod-101
  • productId_2 = prod-102
  • productId_3 = prod-103
  • Input variable prefix: productId
  • Start index for variable: 0 (or 1)
  • End index for variable: \${productId_matchNr}
  • Output variable name: currentProductId
  • Add ”_” before number: Checked

Inside the controller, simply reference \${currentProductId} on every iteration.


5. Transaction Controller (Composite Metrics)

Section titled “5. Transaction Controller (Composite Metrics)”

The Transaction Controller groups multiple HTTP requests into a single parent business transaction (e.g., “Checkout Journey” consisting of /cart/validate, /payment/authorize, and /order/create).

  • Generate parent sample:
    • Checked (Recommended): The dashboard report shows only the consolidated parent transaction line (“Checkout Journey”), keeping reports clean and summarizing total user-perceived latency.
    • Unchecked: Outputs both individual child requests and the parent transaction line.
  • Include duration of timer and pre-post processors in generated sample:
    • Unchecked (Recommended): Measures pure server processing and network latency.
    • Checked: Includes think times and client-side scripting delays in the overall transaction duration.

Routes execution to one specific child element based on:

  • Index: 0 for 1st child, 1 for 2nd child.
  • Name: Value matching the exact name of a child sampler.
  • Value: \${paymentType} → routes dynamically to child sampler named CREDIT_CARD or PAYPAL.

Enforces a hard time cap on child samplers:

  • Runtime (seconds): 60 (threads run child loop continuously for 60 seconds, then exit).
On this page