The Loop Controller in JMeter

The Loop Controller in JMeter

How to repeat part of a test exactly as many times as you need, how it differs from the Thread Group loop, how the numbers multiply, and how to use it without distorting your results.

A chai seller at a railway station does not rebuild his stall for every customer. He sets up once, and then repeats the same small routine again and again: take the order, pour the tea, collect the money. A good load test works in much the same way. A real user logs in once, but may then search ten times, open twenty product pages, or upload five photos in a row. If you wrote out each repeated step by hand, your test would become long, slow to edit, and easy to get wrong. In Apache JMeter, the element that repeats a group of steps for you is called the Loop Controller.

This guide teaches the Loop Controller from zero. You do not need earlier JMeter knowledge. We begin with what a controller is, then look at every setting on the Loop Controller screen, then follow what happens inside JMeter on each pass of a loop. After that we cover the topics that separate a careful engineer from a beginner: how loop counts multiply, how to get a different value on every pass, how to break out of a loop early, what a loop does to your load and your reports, and the mistakes that quietly distort results.

1
Setting that matters most: the loop count
2
Places loops live: Thread Group and Loop Controller
×
Nested loop counts multiply, never add

WWhat Is a Loop Controller?

It is a JMeter element that runs everything placed inside it a set number of times, one pass after another, before moving on.

Starting with the basics

Apache JMeter is a free, open-source tool written in Java that measures how well a system behaves when many users use it at the same time. This is called load testing or performance testing. A JMeter test is arranged as a tree called a Test Plan. The pieces inside the tree are called test elements. Each virtual user is a thread, which is a small worker that walks through the tree independently of the others.

A Sampler is the element that sends one request, such as an HTTP call, and records the answer. Each request and answer pair is one sample. A Controller is an element that decides how and when the samplers beneath it run. Some controllers only group steps together, and others repeat steps, skip steps or choose between them. The Loop Controller is the simplest repeating controller. You give it a number, and it runs its children that many times.

What the Loop Controller really does

The Loop Controller has one main job: repeat. Whatever you place under it, whether one sampler or a long chain of samplers, timers and extractors, is performed from top to bottom, then performed again, until the loop count is reached. Only then does the virtual user move on to the next element after the loop. It does not send anything itself, it does not judge anything, and it does not record anything. It simply controls the flow.

Everyday Analogy

Think of a gym instructor who tells a class, “Do ten push-ups, then move on to the next exercise.” The instructor does not do the push-ups. The instructor only sets how many times the group repeats the movement. The Loop Controller is that instructor, and the samplers beneath it are the exercise.

Why it matters

Loops decide how much work each virtual user performs. If you accidentally set a loop to a hundred instead of ten, your server may receive ten times the traffic you planned. If you forget a loop, your test may send far fewer requests than a real user would. Because loops multiply, a small change can create a very large change in load. Understanding the Loop Controller is therefore not a detail. It is a core part of shaping the traffic your test creates.

i
Key Idea

The Loop Controller repeats a section of your test. Everything beneath it runs again on each pass, and its loop count tells JMeter how many passes to make.

Repeat what real users repeat, and nothing more.

TThe Controller Family: Where Loops Fit

JMeter has a whole family of controllers. Seeing the family makes it clear what the Loop Controller is for, and what it is not for.

Two kinds of controllers

JMeter splits controllers into two groups. Samplers do real work and are sometimes loosely called controllers because they sit in the same part of the tree, but they are really the workers. Logic Controllers are the managers. They hold other elements and decide the order, the count and the conditions under which those elements run. The Loop Controller belongs to the second group.

Repeat

Loop Controller

Runs its children a fixed number of times, or forever if you ask.

Repeat

While Controller

Keeps repeating as long as a condition stays true, such as “job not finished yet”.

Repeat

ForEach Controller

Repeats once for every item in a numbered list of variables, such as a list of product ids found in a response.

Choose

If Controller

Runs its children only when a condition is true.

Choose

Interleave Controller

Runs just one child per pass, rotating through them.

Choose

Random Controller

Picks one child at random on each pass.

Limit

Once Only Controller

Runs its children only once per virtual user, such as a login step.

Group

Transaction Controller

Bundles several samplers into one measured business step.

When to choose which

The Loop Controller is the right tool when you know in advance how many times a section should repeat. If the answer depends on something that happens during the test, such as waiting for a status to change, the While Controller fits better. If the number of repeats depends on the length of a list returned by the server, the ForEach Controller fits better. Using a Loop Controller where a While or ForEach Controller belongs is a common source of tests that run too few or too many passes.

!
Remember

The Loop Controller counts. It never looks at the responses. If the repeat decision depends on what the server says, you need a different controller or a way to break out of the loop, both covered later.

WWhere the Loop Controller Sits in a Test Plan

The position of a Loop Controller in the tree decides what it repeats and what other elements can see inside it.

A typical tree

A normal test starts with the Test Plan, then a Thread Group that sets how many virtual users run and how many times each one repeats the whole scenario. Beneath the Thread Group you place samplers and controllers in the order a real user would act. A Loop Controller is added as a child of the Thread Group or of another controller, and the samplers to repeat are placed under it.

flowchart TD
    A[Test Plan] --> B[Thread Group]
    B --> C[HTTP Request Login]
    B --> D[Loop Controller Browse Products]
    D --> E[HTTP Request Search]
    D --> F[HTTP Request View Product]
    D --> G[Constant Timer]
    B --> H[HTTP Request Logout]
    B --> I[Listener]
Fig 1. Login happens once, the browse section repeats, and logout happens once.

How the user experiences it

Reading the tree above from top to bottom, each virtual user logs in once. It then enters the Loop Controller and performs search, view and a pause. It then does so again, as many times as the loop count says. When the loop is complete, it moves down to logout. The Loop Controller wraps only the section you want to repeat, so the login and logout stay outside it.

Scope in one idea

Scope means which samplers an element affects. An element affects its own level and everything beneath it, like a notice pinned on one floor of a building: everyone on that floor sees it, and other floors do not. A timer placed directly under the Loop Controller applies to every sampler in the loop. A timer placed under the Thread Group applies to every sampler in the Thread Group, including those outside the loop. Choosing where to place each helper is a design decision.

Everyday Analogy

Picture a restaurant with a set menu. Welcoming the guest and presenting the bill happen once. Serving each of the five courses is the repeated part. The Loop Controller is the box drawn around the courses. Anything inside the box repeats for every course. Anything outside happens just once per visit.

i
Tip

Rename the Loop Controller to say what it repeats, such as Browse Products Loop. A clear name makes both the plan and the reports easier to read.

TTour of the Loop Controller Screen

The screen is small, which is part of its charm. A few fields do all the work.

The fields

FieldWhat it doesWatch out for
NameThe label shown in the tree and in reportsLeaving the default name makes several loops hard to tell apart
CommentsA free note for the next person who reads the planUnused, but very useful for explaining why a count was chosen
Loop CountHow many times the children runA very large number multiplies traffic enormously
InfiniteA tick box that makes the loop repeat without endNeeds another way to stop the test, such as a time limit on the Thread Group

Giving the count as a value or a variable

The loop count box accepts a plain number, but it also accepts a variable or a function. A variable is a named value, written between a dollar sign and curly brackets, that JMeter swaps for a real value at run time. This means the count could come from a data file, from a value extracted from a response, or from a setting passed on the command line. A popular approach is to read the count from a property so the same test plan can run a light version for a quick check and a heavy version for the real run, without editing the file.

What a count of zero or a negative number means

A count of zero means the children are skipped entirely. A negative count, such as minus one, is treated as infinite, the same as ticking the Infinite box. Be careful here. If a variable that you use for the count is empty or holds text that is not a number, the loop may behave in a way you did not intend. Always check the value with a debugging element before trusting it.

The loop index

The Loop Controller also exposes a built-in variable that tells you which pass you are on. Its name is made from the controller’s name. If your Loop Controller is called Browse Loop, the variable is the name wrapped with two underscores and the word idx, preceded by the prefix jm. The first pass has the number zero, the second pass has the number one, and so on. Because the name of the variable includes the name of the controller, renaming the controller changes the variable. This is one more reason to choose a stable, simple name early and to avoid spaces and unusual characters.

!
Gotcha

Pass numbers start at zero, not at one. If you show the index on a page or use it to pick a row, remember that the first pass is zero. Mixing up zero-based and one-based counting is a classic off-by-one slip.

HHow Looping Works Internally

Behind the scenes, JMeter treats each controller as a small machine that hands out its children one at a time. Seeing that machine explains many puzzling behaviours.

One thread, one walk through the tree

Every virtual user thread asks the Thread Group for the next thing to run. The Thread Group asks its first child, and each controller in turn hands over its own next child, until a sampler is reached. That sampler runs, and the thread asks again. When a controller runs out of children, it tells its parent it is done, and the parent moves to its next child. The Loop Controller adds one extra rule: when its last child is finished, it checks whether more passes remain, and if so it starts again from its first child instead of reporting that it is done.

flowchart TD
    A[Thread enters Loop Controller] --> B{More passes left}
    B -->|Yes| C[Reset children and set index]
    C --> D[Run each child top to bottom]
    D --> E[Add one to the pass number]
    E --> B
    B -->|No| F[Leave loop and run next element]
Fig 2. The decision the Loop Controller makes before every pass.

What is reset on each pass

At the start of each pass, the controller notifies the elements inside it that a new iteration has begun. Some elements react to this signal. A CSV Data Set Config element placed inside the loop reads its next row of data. A Counter element adds one. Controllers nested inside, such as an Interleave Controller, move forward in their own order. Elements that do not need to react simply run again with whatever values are current.

Each thread has its own loop

The loop state belongs to each virtual user separately. If a Loop Controller is set to five passes and you run a hundred threads, each thread makes five passes of its own, and the total is five hundred passes. The threads do not share a counter and they do not wait for each other. Thread number seven may be on its fourth pass while thread number twelve is on its first.

Everyday Analogy

Imagine a hundred runners on a hundred separate tracks, each told to run five laps. Each runner counts their own laps. One runner finishing early does not change how many laps another runner needs to run.

Passes are not free

Every pass sends real requests. JMeter does not remember what the last pass did and it does not skip work that was already done, unless you add elements that do so, such as a cache manager. This is a feature, because it lets you measure repeated work, and it is also a risk, because repeated identical requests may be answered from the server’s own cache, which can make response times look better than real, varied traffic would.

i
Production Insight

Teams that run long tests often notice that the first pass of a loop is slower than later ones, because connections are being opened and caches are being filled. They either ignore the first pass in analysis or add a short warm-up phase before the measured loop.

LLoop Controller Versus the Thread Group Loop Count

Beginners often see two places to set a repeat count and wonder which one to use. They do different jobs, and they combine by multiplying.

Two kinds of repeating

The Thread Group has its own loop count. It tells each virtual user how many times to run the entire scenario from the first element to the last. The Loop Controller repeats only the section beneath it, and the rest of the scenario runs just once per scenario pass. One is the outer repeat for the whole story, and the other is an inner repeat for a single scene.

QuestionThread Group loop countLoop Controller
What repeats?The whole scenario for each threadOnly the elements inside the controller
Where is it set?On the Thread Group screenOn the Loop Controller screen
Can login run once outside it?No, login repeats on every pass unless you use a Once Only ControllerYes, place login before or outside the loop
Can it be infinite?Yes, with the Infinite option, usually paired with a time limitYes, with its own Infinite tick box
Can there be several in one test?Each Thread Group has oneAs many as you like, even nested

How the two combine

Suppose the Thread Group is set to repeat three times and a Loop Controller inside it is set to repeat four times, with one sampler inside. On each of the three scenario passes, that sampler runs four times. So one thread runs it twelve times. If there are ten threads, the sampler runs one hundred and twenty times in total. The counts multiply. They never add.

3
Thread Group passes per user
4
Loop Controller passes per scenario pass
120
Sampler runs with 10 threads (3 × 4 × 10)

Choosing between them

1

Repeat the whole user journey

Use the Thread Group loop count, or a duration with an infinite count for time-based tests.

2

Repeat one section a fixed number of times

Use a Loop Controller around only that section.

3

Keep setup steps from repeating

Place them outside the loop, or inside a Once Only Controller when they sit under the Thread Group’s own repeat.

!
Watch Out

When someone says “my test sent far more requests than I planned”, the cause is very often a forgotten Thread Group loop count of more than one, multiplied by a Loop Controller. Always compute the total before running.

GGetting Different Data on Every Pass

A loop that sends the same request ten times is rarely realistic. This chapter shows how to make each pass different.

Why variety matters

Servers are clever about repeated questions. They may keep the answer ready in a fast memory called a cache, or they may reject duplicates, such as a second order with the same reference number. If every pass sends identical data, you measure the cache and the duplicate checks, not the real work. Real users search for different words, open different products and submit different forms, so a good loop feeds new data each time.

The tools for variety

Data

CSV Data Set Config

Reads a row from a file each time it is told a new pass has begun, giving each pass a fresh set of values.

Number

Counter

A config element that gives an increasing number on every pass. It can count across all users together, or separately for each user.

Index

Loop index variable

The zero-based pass number exposed by the Loop Controller, handy for choosing which item to use.

Random

Random functions

Built-in functions that give random numbers or strings, useful for search words and unique references.

Unique

Unique id function

Creates a fresh unique identifier for each use, good for order numbers.

Time

Time functions

Produce the current time, useful when a request needs a timestamp.

Where you place the data element matters

A CSV Data Set Config reads its next line when the controller it sits in begins a new pass. If you place it directly under the Thread Group, it moves to a new row once per scenario pass, so every iteration of your inner loop sees the same row. If you place it inside the Loop Controller, it moves to a new row on every inner pass. Neither is wrong. They give different behaviour, and you should choose on purpose.

flowchart LR
    A[Pass starts] --> B[CSV element reads next row]
    B --> C[Variables hold new values]
    C --> D[Sampler sends request with new values]
    D --> E[Next pass starts]
    E --> B
Fig 3. A CSV element inside the loop brings a fresh row to every pass.

Running out of rows

The CSV element has a setting for what to do when the file ends. It can start again from the top, stop the thread, or stop the whole test. If a long loop consumes more rows than the file contains, recycling the file reuses old values, and stopping the thread cuts the loop short. Count your rows against the total passes: threads times scenario passes times loop passes, whenever each pass needs a new row.

Everyday Analogy

Think of a teacher calling out names from a roll at the start of every class period. If the roll has thirty names but there are forty periods, the teacher must decide what to do: start the list again or stop calling. The CSV element faces the same choice when its file ends.

i
Habit

Before a big run, write the formula for how many rows you need on a sticky note. If the data file is shorter than the answer, either extend the file or choose the recycle option on purpose.

NNested Loops and the Mathematics of Load

A loop inside a loop is perfectly legal, and perfectly dangerous if you do not count carefully.

The multiplication rule

When one Loop Controller sits inside another, the inner section runs once for every pass of the outer one. The total number of runs of the innermost sampler is the product of every count above it: threads, Thread Group passes, outer loop passes, inner loop passes. A modest looking structure can produce a very large number.

ThreadsThread Group passesOuter loopInner loopRuns of the innermost sampler
10154200
502101010,000
20052020400,000
50010505012,500,000

Notice how the last row reached twelve and a half million requests from numbers that each look harmless. A tester who intended to send a few thousand could flood a staging environment by accident. This is why experienced engineers always multiply the counts before pressing start.

A real use for nesting

Nesting is useful when a real behaviour has two levels. Imagine a user who opens five search result pages, and on each page opens three product pages. The outer loop runs five times for pages. The inner loop runs three times for products. The search sampler sits in the outer loop, and the product sampler sits in the inner loop. The totals are five searches and fifteen product views per scenario pass, which matches the story.

flowchart TD
    A[Outer Loop 5 passes] --> B[Search Results Page]
    A --> C[Inner Loop 3 passes]
    C --> D[Open Product Page]
Fig 4. Nested loops: each outer pass opens a page of results, and the inner loop opens three products from it.

Estimating request rate

Counts tell you the total number of requests. To understand the load per second, you also need the time each pass takes. If a pass takes two seconds, including pauses, and a hundred threads are all looping, the system sees about fifty requests per second per sampler in the loop. If you remove the pauses and the server answers in a tenth of a second, the same hundred threads create about a thousand requests per second. Pauses and response times are part of the loop’s arithmetic.

!
Safety Rule

Do the multiplication on paper before every large test, and share the numbers with the team that owns the system under test. Surprises of this kind are what turn a planned test into an outage.

HHelpers Inside a Loop: Timers, Extractors and Assertions

Other elements behave in particular ways when they live inside a loop. Knowing the rules prevents silent mistakes.

Timers: pauses on every pass

A timer adds a pause before a sampler runs, to imitate a person reading or thinking. A timer placed inside a Loop Controller applies to every sampler in the loop, and it fires on every pass. If three samplers and one timer sit in the loop, the pause happens before each of the three, on every pass. If you wanted only one pause per pass, place the timer under the one sampler that should be preceded by it, or use a Flow Control Action sampler set to pause. Without any timer, a loop runs as fast as the server can answer, which is rarely realistic.

Extractors: values are overwritten

An extractor reads a value out of a response and stores it in a variable. Inside a loop, the same extractor runs on every pass, and each pass overwrites the variable from the previous pass. If you need to remember every value across the loop, give the extractor a way to store them separately, for example by building the variable name from the pass number, or by saving values to a file. If you only need the newest value, such as the latest token, the overwriting is exactly what you want.

Assertions: checking every pass

An assertion decides whether a response is correct. Inside a loop it checks every pass. A failure on pass seven is recorded as a failure for that pass only, and later passes continue unless you tell the Thread Group to stop on error. Because a loop multiplies samples, a tiny failure rate can still produce many failed samples, so watch percentages as well as counts.

Config elements inside a loop

Scope

Header and Cookie Managers

Normally placed at Thread Group level so they cover the whole scenario. Cookies carry over from one pass to the next, so a user stays logged in throughout the loop.

Scope

HTTP Request Defaults

Shared host and port settings for every sampler in scope, loop or not.

Data

User Defined Variables

Set once at the start of the test, so they do not change from pass to pass.

Data

Random Variable

Gives a new random value each time it is read, useful for varied choices on every pass.

Transaction Controllers and loops

A Transaction Controller bundles several samplers into one measured business step, such as “Add To Cart”. You can place it inside the loop, so each pass creates one transaction result, or you can place the loop inside the transaction, so the whole loop is measured as a single step. The first shows how each repetition performs, and the second shows how long the whole repeated activity took. Choose according to the question you want the report to answer.

i
Tip

Keep the Cookie Manager outside the loop at Thread Group level. If it is placed inside, it may be reset in ways that log the user out on every pass, which is a very confusing problem to chase.

OOnce Only, While, ForEach and the Other Controllers Compared

Loops rarely stand alone. They work best when combined with the other logic controllers, and each of those has its own rules.

The Once Only Controller inside a loop

The Once Only Controller runs its children a single time. Its behaviour inside a loop is easy to misread. When it sits under a Loop Controller, it runs on the first pass of that loop and is skipped on the others. If the outer structure starts the Loop Controller again, for example because the Thread Group repeats the scenario, then the Once Only Controller runs again on the first pass of that new start. So “once” means “once per start of the loop it lives in”, and not “once in the whole test”.

flowchart TD
    A[Loop Controller 5 passes] --> B[Once Only Controller]
    A --> C[HTTP Request Search]
    B --> D[HTTP Request Fetch Token]
    D -.->|runs on pass 1 only| C
Fig 5. The token request inside Once Only runs on the first pass, and the search runs on all five.

While and ForEach for conditions and lists

The While Controller repeats as long as a condition is true. The condition is a small expression that you write, often based on a variable set by an extractor. A typical use is polling: ask for the status of a job until it says finished. The ForEach Controller repeats once for each item in a numbered set of variables, such as a list of product identifiers extracted from a response, handing the current item to the children on each pass. Use the Loop Controller only when the count is known in advance.

ControllerRepeats whenExample
Loop ControllerFor a count you decided in advanceOpen ten search pages
While ControllerWhile a condition remains trueCheck job status until finished
ForEach ControllerOnce per item in a list of variablesOpen every product found in a search
Once Only ControllerOnly on the first pass of the loop it sits inFetch a token one time
Interleave ControllerOne child per pass, in rotationAlternate between three search types
Throughput ControllerFor a chosen share of passes or executionsRun checkout for thirty percent of users
Everyday Analogy

A Loop Controller is like saying “knock on the door three times”. A While Controller is like saying “keep knocking until someone answers”. A ForEach Controller is like saying “knock on every door on this list”. The first has a fixed count, the second depends on what happens, and the third depends on how long the list is.

!
Remember

If you ever find yourself setting a huge loop count and then breaking out early when a condition is met, a While Controller is probably the cleaner design.

BBreaking Out of a Loop and Controlling the Flow

The Loop Controller itself has no exit condition other than its count. When you need to leave early, you combine it with other elements.

Why you might leave early

Imagine a loop that opens twenty pages of results, but the server answers an error on page six, or the account runs out of items. Carrying on for fourteen more passes wastes time, creates a pile of pointless failures, and pollutes your numbers. In real life, a user would stop. Your test should too.

The usual recipe

Place an If Controller inside the loop. Its condition checks a variable, such as “the response said no more results”. Inside the If Controller, place a Flow Control Action sampler. This special sampler does not send a request. It performs an action on the flow of the test, and it offers choices such as pausing for a given time, going straight to the next pass of the loop, breaking out of the current loop, starting the next scenario pass for this thread, or stopping the thread or the whole test. Choosing “break current loop” ends the Loop Controller early and continues with the element after it.

flowchart TD
    A[Start pass] --> B[Search request]
    B --> C{No more results}
    C -->|Yes| D[Flow Control Action break current loop]
    C -->|No| E[Open product page]
    E --> F[Next pass]
    D --> G[Continue after the loop]
    F --> A
Fig 6. An If Controller and a Flow Control Action give the loop an early exit.

What the Thread Group does on errors

The Thread Group has a setting that decides what happens after any sampler fails. The choices are to continue, start the next scenario pass for that thread, stop that thread, stop the test gracefully, or stop the test immediately. This matters for loops. If you choose “start next thread loop”, a failure inside a loop jumps out of the whole loop and out of the rest of that scenario pass, which is a hidden early exit. If you choose “continue”, every remaining pass is attempted, even when an early failure makes the later ones meaningless. Think about what a real user would do after the first failure and pick the matching setting.

Action

Go to next loop iteration

Skips the rest of this pass and starts the next one.

Action

Break current loop

Leaves the nearest Loop Controller and carries on after it.

Action

Start next thread loop

Abandons the rest of the scenario pass and begins the next one.

Action

Stop thread

Ends this one virtual user while others carry on.

Action

Pause

Waits for a stated number of milliseconds, handy for polling gaps.

Action

Stop test

Ends the entire run, either gracefully or at once.

!
Gotcha

Breaking out of a loop on a failure also hides the failure from the later passes that never ran. Your sample counts will be lower than the plan predicted. Always compare actual counts to expected counts so silent early exits are noticed.

DData Flow and Lifecycle of a Looping Test

To trust a looping test, you need to know what carries over from pass to pass and what starts fresh.

What carries over

1

Variables

Values stored by extractors or functions stay until they are overwritten. A value from pass two is still visible in pass three unless something replaces it.

2

Cookies and sessions

A Cookie Manager keeps cookies across passes, so the user stays logged in, unless you clear them.

3

Connections

With KeepAlive on, the network connection from an earlier pass is reused, as a browser would do.

4

Cache entries

If a Cache Manager is present, files downloaded on earlier passes are remembered and may not be fetched again.

What starts fresh

Each pass starts with the first child again, with the pass index moved forward, and with any iteration-aware elements, such as CSV or Counter elements, advanced. Timers run again. Assertions run again. Result records are created again, and each sample is a new entry in the result file.

The stale value trap

A stale value is an old value that you wrongly keep using. Suppose an extractor fails on pass six, because the page changed. The variable still holds the value from pass five. The next request is sent with a number that was valid a moment ago, and perhaps no longer is. The test then shows odd errors that seem unrelated to the real cause. To avoid this, give the extractor a clear default text that signals failure, and add an assertion that checks the value is present before it is used.

Everyday Analogy

Think of a whiteboard that is only partly wiped between lessons. A number written in the first lesson stays visible in the second unless someone rubs it out or writes over it. If the teacher forgets to write a new number, students read the old one and get confused. Variables in a loop behave like that whiteboard.

The state of each thread is private

Variables, cookies and counters belong to a single thread unless you ask for sharing. A shared Counter, or properties that every thread can read, can be used for shared state, but then threads can influence each other. Use sharing carefully, because it can make a test non-repeatable.

i
Debugging Hint

Place a Debug Sampler inside the loop for a single-user trial run, and read the variables on each pass. Seeing the values change with your own eyes is the fastest way to catch stale data.

PPerformance and Scalability Concerns

A loop can quietly turn a polite test into a hammer. These concerns explain how to keep your load realistic and your load generator healthy.

The tight loop problem

A tight loop is a loop with no pause. Each virtual user fires its next request the instant the last answer returns. A fast server answers in milliseconds, so one thread can send hundreds of requests per second. A hundred threads in tight loops can create tens of thousands of requests per second, far above what a hundred real people could ever produce. The server may fail, and the report will say the system cannot handle a hundred users, which is untrue. It could not handle a hundred robots with no manners.

0 ms
Pause in a tight loop, creating unrealistic traffic
3–10 s
Typical human think time between page actions
Rate
Threads divided by pass time gives requests per second

Think time and pacing

Add timers so the pace per user resembles a real person. When you need a specific number of requests per second regardless of response time, use a throughput-shaping approach, such as the Constant Throughput Timer, which slows threads to hit a target rate. Together, these tools let you say “this loop creates about this many requests per second”, and then compare that to what your real traffic would be.

Load on the generator

Memory

Many samples

Every pass makes new samples. Heavy listeners that store them all will fill memory in long loops.

CPU

Frequent extraction

Extractors and assertions run on every pass, so costly patterns are costly many times over.

Disk

Large result files

Millions of samples create large files. Save only the fields you need.

Network

Constant traffic

A tight loop can saturate the generator’s own network link before it stresses the server.

Infinite loops and time-bound tests

A loop count of infinite is common in soak tests, which run for hours to find slow problems such as memory leaks. An infinite loop never ends by itself, so you must give the test another way to stop. The Thread Group offers a scheduler with a duration, which ends the test after a set time. Always pair infinite loops with a duration, and always make sure the loop includes a sensible pause.

!
Danger

An infinite loop with no duration and no pause is the classic way to leave a test running over a weekend, hammering a shared environment. Always set a time limit before pressing start.

Scaling out

When one machine cannot generate enough load, JMeter can distribute the same plan across many machines. Each machine runs its own copy of every loop. If the plan says a hundred threads with ten passes, and you use five machines, you get five hundred threads and five thousand passes in total. Remember to divide thread counts by the number of machines when you plan the load.

SSafety, Security and Responsible Use

Loops make it very easy to generate a large amount of traffic and a large amount of data. Both can cause harm if handled carelessly.

Test only what you are allowed to test

Sending a flood of repeated requests to a system you do not own, or have no written permission to test, can disrupt that service and may be illegal. Always test systems you own, or where the owner has clearly agreed, preferably in a separate environment that mirrors production. Warn the people who operate the system before a heavy run, because unannounced repeated traffic looks exactly like an attack to security tools.

Loops that create data

A loop that places an order, creates an account or uploads a file creates real records every time. Ten thousand passes can leave ten thousand orders in a database. In a shared environment, that can fill storage, confuse other teams and trigger real emails or payments if the system is connected to live services. Plan how the test data will be cleaned up, use dedicated test accounts, and make sure external services such as email and payment gateways are replaced with safe stand-ins.

Rule

Use test accounts

Create special users with fake data and limited rights, never real customer details.

Rule

Plan cleanup

Have a script or process that removes test orders and files after the run.

Rule

Cap the totals

Decide the maximum records any loop may create and check the arithmetic before starting.

Rule

Protect secrets

Keep passwords and tokens out of the plan file and out of result files wherever possible.

Rate limits and blocking

Many systems protect themselves by limiting how many requests one user or address can send. A loop with no pauses, run from a single machine, can trigger that protection, and the server then answers with errors that have nothing to do with real capacity. Know whether such protection exists, and agree with the owners whether to relax it for the test environment.

i
Before Every Heavy Run

Confirm three things in writing: you have permission, the totals are calculated and agreed, and a person knows how to stop the test quickly if something goes wrong.

MMonitoring, Logging and Debugging Loops

Loops can fail in quiet ways. A few simple habits let you see exactly what each pass did.

The debugging toolkit

See

View Results Tree

Shows each sample with its request and response. Use it with one user and a small loop count.

See

Debug Sampler

Prints the current variables so you can watch values change from pass to pass.

Check

Response Assertion

Fails a sample when the response is not what was expected.

Log

Log elements

A scripting element can write the pass number into the JMeter log when you need a precise trace.

Count

Summary Listener

Shows how many samples each sampler produced, so you can compare with the arithmetic.

Read

JMeter log file

Records warnings and errors from the tool itself, such as a loop count that could not be read as a number.

A reliable routine

1

Shrink the loop

Run one user, a loop count of two or three, and a single scenario pass.

2

Count the samples

Check that each sampler ran the number of times your arithmetic predicted.

3

Watch the variables

Use a Debug Sampler to confirm each pass gets new values, and that nothing stale is reused.

4

Test the exit

Force the exit condition and confirm the loop leaves when it should.

5

Scale up gradually

Raise users, then loop count, watching errors at each step.

Monitoring during a long loop

For tests that run for hours, watch both sides. On the load generator, watch processor use, memory and disk space, because a long loop produces a lot of data. On the server side, watch its own resources, queue lengths and error logs. A slow upward drift in response time across hundreds of passes often points to a leak or a growing queue. That kind of trend is exactly what looping soak tests are designed to find.

i
Habit

Run the final settings first in a small trial of a few minutes, and read the sample counts before starting the long run. If the numbers do not match the plan, fix them while it costs minutes, not hours.

RReading Reports from Looping Tests

When a sampler runs many times, your reports fill with repeated entries. Knowing how to read them keeps the story clear.

Names group the samples

Listeners and reports group samples by the name of the sampler. Every pass of a looped sampler has the same name, so all passes are merged into one row with a large sample count. This is usually what you want, because the average, the percentiles and the error rate then describe the sampler across all passes. A different pass number does not create a different row.

Should the pass number go in the name?

JMeter allows a variable in a sampler’s name, so it is possible to make “Search page 1”, “Search page 2” and so on. This is tempting but usually wrong for long loops. It creates one report row for every distinct name, which can balloon into thousands of rows and make the report unreadable. Use it only for very short loops where you truly want a separate row for each pass. For most tests, keep a single name and use the pass number only in the data you send.

Transactions give a business view

If the loop represents a business action such as “browse ten pages”, wrap the whole loop in a Transaction Controller to get one measured result for the entire browse, in addition to the individual samples. Teams then set targets on the business step, such as “browsing ten pages must finish within thirty seconds”, which is easier for non-technical readers to understand than a list of request times.

Beware of averages

With many passes, averages can hide trouble. A slow first pass, caused by cold caches, is diluted by many fast later passes. Percentiles, such as the 90th and 95th, show the unlucky end of the experience. If the first pass matters to real users, as it does for a first visit, consider measuring it separately by placing it outside the loop.

!
Watch Out

Do not compare a looping test with a non-looping test as if they were the same. Repeated requests may hit caches, reuse connections and warm up the system, which flatters the numbers. Compare like with like.

DDesign Patterns and Anti-patterns

Experienced engineers use a few reliable loop designs, and avoid a handful of tempting shortcuts that cause trouble later.

Patterns that work

Pattern

Setup outside, repeat inside

Log in once before the loop, repeat only the activity that real users repeat, and log out after.

Pattern

Count from a property

Read the loop count from a setting that can be changed on the command line, so one plan serves small and large runs.

Pattern

Data per pass

Feed each pass from a data file or counter so requests differ.

Pattern

Pause inside the loop

Add a timer so the pace matches human behaviour.

Pattern

Early exit on a condition

Combine an If Controller with a break action so the loop ends when the story ends.

Pattern

Transaction around the loop

Wrap the loop to report a business step, not only raw requests.

Anti-patterns to avoid

ANTI-PATTERN 01Avoid
What people do

They put login inside the loop so every pass logs in again.

Why it hurts

The load on the login service becomes many times higher than real traffic, and the numbers describe a test that no real user behaves like.

Do this instead

Log in once outside the loop, or use a Once Only Controller, and repeat only the activity that really repeats.

ANTI-PATTERN 02Avoid
What people do

They leave a tight loop with no pause and a very large count.

Why it hurts

The traffic is far beyond what real users produce. The server fails, and the test blames the wrong cause.

Do this instead

Add think time, or use a throughput timer to reach a specific, realistic request rate.

ANTI-PATTERN 03Avoid
What people do

They send identical data on every pass.

Why it hurts

Caches answer repeated questions, and duplicate checks reject repeated actions, so the test measures shortcuts, not real work.

Do this instead

Vary the data on every pass with a data file, counter, or random function.

ANTI-PATTERN 04Avoid
What people do

They nest loops without doing the arithmetic.

Why it hurts

Counts multiply, and the test sends many times more requests than planned, flooding the target and filling result files.

Do this instead

Multiply every count on paper, agree the total with the system owners, and confirm sample counts after a tiny trial.

BBest Practices and Common Mistakes

These are the habits that experienced performance engineers repeat on every project, and the slips that beginners make again and again.

Best practices checklist

AreaDo thisWhy
NamingGive each Loop Controller a clear, simple nameMakes the plan readable, and the loop index variable depends on the name
CountsWrite the total request arithmetic before every runLoop counts multiply, and surprises are costly
SetupKeep login and setup outside the loopAvoids unrealistic load on setup services
PaceAdd timers inside the loopPrevents tight loops and unreal traffic
DataVary data on every passAvoids cache hits and duplicate rejections
ExitProvide an early exit on failure or end of dataReal users stop, and so should the test
LimitsUse a duration with any infinite loopGuarantees the test ends
ControlRead counts from propertiesOne plan serves both quick checks and full runs
CheckingCompare actual sample counts to the planReveals silent early exits and mistakes

Common mistakes

  • Forgetting that the Thread Group also has a loop count, and so multiplying traffic by accident.
  • Putting a Cookie Manager inside the loop, which can log the user out on every pass.
  • Putting the CSV element in the wrong place, so rows are read at the wrong pace.
  • Assuming the Once Only Controller means once per test, when it means once per start of the loop it lives in.
  • Reading the pass index as one-based when it starts at zero.
  • Using a Loop Controller where a While or ForEach Controller was needed.
  • Leaving an infinite loop running with no duration and no pause.
  • Putting the pass number into sampler names for a long loop, producing thousands of report rows.
  • Trusting averages that blend a slow first pass with many fast later ones.
i
Final Check Before a Big Run

Run one user through one scenario pass with a loop count of two. Confirm the sample counts, the data on each pass, and the exit behaviour. Only then raise the numbers.

RReal-World and Industry Examples

Here is how teams use loops in different kinds of systems. These are illustrative patterns that show the scale and care involved, not descriptions of any company’s private tooling.

Online shopping: filling a cart

Large shopping platforms such as Amazon or Flipkart see customers who add several items to a cart before paying. A test models this with a Loop Controller around the “add to cart” request. The loop count comes from a property, say three for an ordinary basket and ten for a heavy one. A data file supplies a different product on each pass, and a short timer imitates the shopper choosing. Login stays outside the loop, and checkout happens once after it.

Search results pagination

A user who searches for a phone may read the first five pages of results. A Loop Controller of five passes repeats the “open next page” request, with a Counter element supplying the page number. If the search returns fewer pages than expected, an If Controller and a break action leave the loop early, exactly as a real user would stop when results run out.

Ride-hailing location updates

In a ride-hailing service such as Uber, a driver’s app sends location updates every few seconds while a trip is in progress. A test uses a Loop Controller to send a series of updates per virtual driver, with a timer of a few seconds between passes and a function that moves the position slightly each time. Thousands of simulated drivers produce a steady stream that tests the system’s ability to ingest continuous data.

Video streaming in chunks

Video services such as Netflix break a film into small chunks that the player fetches one after another. A test models a viewing session as a loop that requests the next chunk each pass, with a pause close to the length of the chunk. A long loop represents a long viewing session, and watching response times across many passes shows whether the service stays steady during a feature-length film.

Bulk upload of records

A bank or a government portal may accept a batch of records from a company in one go. A test uses a Loop Controller to submit a series of records, with unique references from a function, and a Counter to track how many were sent. A cap on the loop count protects the test database, and a cleanup process removes the created records afterwards.

What these examples share

In every case, the loop is a small part of a bigger design. Its power comes from the arrangement around it: setup outside, varied data inside, human pacing, early exits and arithmetic checked in advance.

TTrade-offs and Limits to Know

The Loop Controller is simple and reliable, and it has clear edges. Knowing them helps you choose the right tool.

Advantages

  • Very easy to understand and to set up
  • Keeps the plan short by avoiding copied samplers
  • Count can come from a property or variable for flexible runs
  • Works the same in single machine and distributed runs
  • Exposes a pass index for building varied data

Disadvantages

  • Counts only, with no built-in exit condition
  • Multiplies traffic and data in ways that are easy to forget
  • Repeated identical requests can flatter results through caching
  • Nested loops can become hard to read and reason about
  • Reports merge all passes unless names or transactions separate them

Closed model versus open model

A looping thread is a closed model. A fixed number of users each wait for an answer before the next request. If the server slows down, the users send fewer requests, and the pressure on the server falls, which can hide how bad things get. Real internet traffic is closer to an open model, where new users keep arriving at a certain rate whether or not the server is slow. To explore this, teams use throughput-controlling elements or special thread group plugins that fix the arrival rate. Knowing which model your loop creates helps you interpret the numbers correctly.

Coordinated omission in simple words

When a server stalls for ten seconds, a looping thread simply waits and sends nothing during that time. The long wait is recorded once, even though in real life many users would have arrived during the stall and suffered the delay. The resulting percentiles look better than reality. This effect is called coordinated omission. It does not mean loops are wrong. It means you should read the percentiles knowing how the load was generated, and complement closed loops with fixed-rate tests when tail latency matters.

Everyday Analogy

Imagine a toll booth that jams for ten minutes. A test that sends one car at a time, and waits for each to pass, sees just one very slow car. Real traffic would have kept arriving and queued up by the hundreds. The single slow car understates the pain.

Choosing other tools when needed

If the repeat depends on a condition, use a While Controller. If it depends on a list, use a ForEach Controller. If the scenario itself must repeat for the whole user journey, use the Thread Group loop count or duration. If the load must arrive at a fixed rate, use a throughput timer or an arrival-rate thread group plugin. The Loop Controller is one tool among several, and a good design often uses more than one.

FFrequently Asked Questions

Short, direct answers to the questions people ask most often about the Loop Controller.

Q1What does the Loop Controller do?
It repeats the elements placed beneath it a set number of times, or without end if you tick Infinite. It does not send requests itself.
Q2What is the difference between the Loop Controller and the Thread Group loop count?
The Thread Group loop count repeats the entire scenario for each thread. The Loop Controller repeats only the section beneath it. When both are used, the counts multiply.
Q3If the Thread Group repeats three times and the Loop Controller four times, how many times does a sampler inside run per thread?
Twelve times, because three multiplied by four equals twelve. With ten threads, the total is one hundred and twenty.
Q4Can I use a variable for the loop count?
Yes. The count field accepts a variable or a function, so the value can come from a property, a data file or an earlier response. Check the value first, because a blank or non-numeric value can cause odd behaviour.
Q5What does a loop count of zero or minus one mean?
Zero means the children are skipped entirely. A negative value such as minus one is treated as infinite.
Q6How do I know which pass I am on?
The Loop Controller exposes an index variable whose name is built from the controller’s name. The first pass is zero, the second is one, and so on.
Q7How do I get new data on every pass?
Use a CSV Data Set Config inside the loop, a Counter element, the pass index, or random and unique-id functions. Where you place the element decides when it moves to the next value.
Q8How do I exit a loop early?
Place an If Controller inside the loop with a condition, and inside it a Flow Control Action sampler set to break the current loop. The loop ends and the test continues after it.
Q9When should I use a While Controller instead?
Use a While Controller when the number of repeats depends on something that happens during the test, such as waiting for a job status to say finished. Use the Loop Controller when the count is known in advance.
Q10What does the Once Only Controller do inside a loop?
It runs its children on the first pass of the loop it sits in, and skips them on later passes. If the loop is started again, for example by a repeating Thread Group, it runs again on that first pass.
Q11Why did my test send far more requests than I expected?
Most likely loop counts multiplied. Check the Thread Group loop count, every Loop Controller above the sampler, and the number of threads. Multiply them together.
Q12Do timers inside a loop run on every pass?
Yes. A timer applies to every sampler in its scope and fires before each of them on every pass. Place it carefully if you want just one pause per pass.
Q13Is it safe to run an infinite loop?
It is safe only with another stopping rule, such as a duration on the Thread Group, and with a realistic pause. An infinite loop with neither can run indefinitely and hammer the system.
Q14Will my report show each pass separately?
No. Reports group by sampler name, so all passes of one sampler form one row. Wrap the loop in a Transaction Controller if you want one result for the whole repeated activity.
Q15Why do my loop results look faster than real life?
Repeated identical requests may be answered from caches, and reused connections skip setup costs. Vary the data, use a cache manager sensibly, and treat early passes separately from later ones.

SSummary and Key Takeaways

The Loop Controller is a small element with a large effect. It decides how much work each virtual user performs, and so how much load your test creates.

Key Takeaways

  • It repeats a section. The Loop Controller runs everything beneath it a set number of times, or forever if ticked Infinite, and sends nothing itself.
  • Counts multiply. Threads, Thread Group passes and every nested loop multiply together, so always calculate the total before running.
  • Know the two loops. The Thread Group repeats the whole scenario, and the Loop Controller repeats only one section, so keep setup steps outside it.
  • Make each pass different. Use data files, counters, the zero-based pass index and random functions, and place the data element where it moves at the right pace.
  • Pace and exit on purpose. Add think time to avoid tight loops, and use an If Controller with a break action, or a While Controller, when the story should end early.
  • Read the results with care. Repeated requests can flatter numbers through caching, reports merge passes by name, and averages hide slow first passes.
  • Be safe. Pair infinite loops with a duration, plan cleanup for created data, test only what you are allowed to test, and warn system owners before heavy runs.