JMeter Logic Controllers: If, Loop, and Transaction Controllers
How JMeter's Logic Controllers (If Controller, Loop Controller, Transaction Controller) shape test flow and how to use them without breaking your results.
Logic Controllers determine the order and conditions under which samplers execute. They don’t generate requests themselves — they control flow around the samplers that do.
Transaction Controller — the most important one for reporting
Groups multiple samplers into a single logical “transaction” in the results (e.g. group a login page’s HTML request, CSS, and JS into one “Login Page” transaction rather than three separate rows). Check “Generate parent sample” to roll up timing into one aggregate result; this is essential for making reports readable when a single business transaction spans several HTTP requests, and it’s the standard way to measure “checkout flow” or “search and view results” as one meaningful unit rather than a pile of individual request rows.
If Controller
Executes its children only if a condition (a JMeter expression evaluating to true/false) holds — for example, only attempt a “retry” sampler if a previous extractor failed to find a value, or branch behavior based on a parameterized user “type” (free vs. paid tier) to model realistic traffic mix.
Loop Controller
Repeats its children a fixed number of times, independent of the Thread Group’s own loop count — useful for modeling a sub-flow that repeats more or less often than the outer test iteration (e.g. “add 3 items to cart” inside one larger checkout iteration).
Once Only Controller
Executes its children exactly once per thread, regardless of the Thread Group’s loop count — the standard place for login, which should happen once per virtual user session, not once per loop iteration if the Thread Group loops multiple times to simulate a longer session.
Random Controller / Throughput Controller
Random Controller picks one of its children at random each time it executes — useful for modeling varied user behavior (some users search, some browse categories) without scripting separate Thread Groups for each. Throughput Controller executes its children a target percentage of the time, giving more deterministic control over traffic mix than pure randomness (e.g. exactly 70% of iterations browse, 30% search).
Interleave Controller
Alternates between its children on successive executions rather than running them all every time — useful for round-robining between multiple API endpoints or test data variants.
A realistic composition
A common, realistic structure: Once Only Controller (login) → Loop Controller or the Thread Group’s own loop (main session) → Throughput Controller (mix of browse/search/purchase behavior) → Transaction Controllers wrapping each business flow for clean reporting. Building scripts this way, rather than as one flat list of samplers, is what makes a JMeter test plan actually represent realistic user behavior instead of a mechanical repeat of one fixed sequence.
Takeaway: Transaction Controllers are worth adding to almost every non-trivial script purely for reporting clarity — without them, a report full of individual request rows makes it hard to reason about business-level performance at all.
Comments are powered by Giscus (GitHub Discussions). Enable them by
configuring GISCUS in src/consts.ts — see
giscus.app.