Sampler Result in JMeter: The Complete Advanced Guide

Sampler Result in JMeter: The Complete Advanced Guide

Learn what a Sampler Result contains, how every timing, size, status and thread field is measured, how extractors, assertions and listeners use it, how results are saved and reported, and how to read and protect this data like a performance expert.

Think about a courier company. Every parcel has a tracking record: when it was picked up, when it left the warehouse, when the first update arrived, when it was delivered, how heavy it was, who signed for it, and whether anything went wrong. Without these records, nobody could say whether the company is fast or slow, and nobody could find out where a lost parcel went. A JMeter test is similar. Every request it sends creates a tracking record, and that record is called the Sampler Result.

Every chart, every percentile, every error table and every pass or fail decision in a JMeter report is built from Sampler Results. If you understand this one object well, you can trust your numbers, debug failures quickly, and avoid the quiet mistakes that make test reports misleading. This guide walks through the Sampler Result from the basic idea to the advanced topics that experienced performance engineers care about.

1What Is a Sampler Result?

The record that JMeter writes after every single request.

The simple definition

A sampler is a JMeter element that does one piece of work, such as sending an HTTP request, running a database query, or calling a message queue. Each time a sampler runs, JMeter measures what happened and stores the facts in a package. That package is the Sampler Result, often called a sample result or simply a sample. One run of one sampler by one thread produces one Sampler Result.

The package holds the name of the step, the time it took, the status code, the size of the data, the thread that ran it, whether it passed, and much more. It can also hold the full request and the full response if you choose to keep them. Because every report is made of these packages, a mistake in understanding them leads to a mistake in understanding the whole test.

Simple Analogy

A Sampler Result is like a receipt from a shop. The receipt shows what you bought, when, how much you paid and whether the payment worked. A shop owner who wants to know the day’s business adds up thousands of receipts. A JMeter report adds up thousands of Sampler Results in exactly the same way.

Why it deserves your attention

Most people look at the summary table at the end of a test and never open a single result. This is risky. A summary can show an average of one second while the individual results show that one request in twenty took ten seconds, or that half of the “successful” requests actually returned an error page with a normal status code. The summary only tells the truth when the results underneath are correct and well understood.

i
Practical Tip

Before you run any large test, run it with one or two threads and open a few individual Sampler Results. Check the status, the response and the timings with your own eyes. Five minutes of this saves hours of confusion later.

2Sampler, Sample Result, Assertion Result and Listener

Four neighbouring words that are often mixed up.

JMeter has many moving parts, and the vocabulary around results can be confusing. Clear definitions help you talk to your team and read the documentation without getting lost.

Term 1

Sampler

The element that performs an action, such as an HTTP request, a JDBC query or a script step. It is the cause of a result.

Term 2

Sampler Result

The record created by a sampler run. It stores timings, status, sizes, data and thread details. It is the effect of a sampler run.

Term 3

Assertion Result

A small verdict attached to a Sampler Result by an assertion element. It says whether a check, such as “the page must contain this text”, passed or failed.

Term 4

Listener

An element that receives finished Sampler Results and shows, summarises or saves them, for example as tables, graphs or files.

Term 5

Sample

The everyday word for one Sampler Result. When a report says “1,000 samples”, it means 1,000 Sampler Results.

Term 6

JTL File

The results file that stores Sampler Results, one row or one record per sample, so that they can be analysed after the test.

How they relate

The relationship is a simple chain. A sampler runs and creates a Sampler Result. Assertions look at the result and attach their verdicts. Listeners then receive the result and turn it into something a human can read or a file that a tool can process. Understanding this chain tells you where to look when something is wrong. If a number looks wrong, it may be a problem in what the sampler measured, in what an assertion decided, or in what a listener chose to save or display.

!
Common Misconception

Many beginners think the listener measures the response time. It does not. The sampler measures. The listener only displays and stores what the sampler measured. A listener can hide fields or summarise them, but it cannot create information that the sampler never collected.

3Where the Sampler Result Appears in the Execution Order

Knowing the order of events explains why some elements can see the result and others cannot.

JMeter follows a fixed order every time a sampler is about to run. Understanding this order tells you when a Sampler Result is born and who may touch it.

flowchart TD
    A["Configuration elements apply their settings"] --> B["Pre-processors run"]
    B --> C["Timers calculate and apply their delays"]
    C --> D["Sampler runs and measures the request"]
    D --> E["Sampler Result is created"]
    E --> F["Post-processors read the result and extract values"]
    F --> G["Assertions check the result"]
    G --> H["Listeners receive the finished result"]
        
FIG 1 — The life of a Sampler Result inside one sampler run

The sequence in plain words

1

Preparation

Configuration elements such as default settings and managers prepare the request. Pre-processors can change variables or the request itself just before it is sent.

2

Waiting

Timers add their pauses. This waiting happens before the sampler starts the clock, so the pause is not part of the measured response time.

3

Sampling

The sampler sends the request, waits for the response and records the start time, the end time and other measurements. The Sampler Result is created here.

4

Reading and checking

Post-processors read the result to capture values such as tokens. Assertions then judge the result and add their verdicts, which may change the success flag.

5

Publishing

Listeners receive the final version of the result and display it or write it to a file. After this, the result is normally released from memory.

Simple Analogy

Think of a restaurant order. The waiter first prepares the table, then waits until the kitchen is ready, then the kitchen cooks and serves the dish. A reviewer checks the dish, and finally the manager records it in the daily log. The log entry is the Sampler Result, and each person touches it at a different stage.

Why the order matters in practice

Because timers run before the sampler starts measuring, a five-second think time never appears in the response time of the request. Because assertions run after post-processors, an extractor can capture a value from a response even if an assertion later marks that same response as failed. Because listeners come last, they always see the final status after all assertions have spoken. These simple facts explain many puzzling situations that confuse beginners.

i
Scope Reminder

Timers, assertions, pre-processors and post-processors apply only to the samplers within their scope, which is decided by where they sit in the test plan tree. An assertion placed at the top of a thread group checks every sampler below it. The same assertion placed inside a single sampler checks only that sampler. Misplaced elements are a common cause of “why did this check fail on a request I never meant to check”.

4Anatomy of a Sampler Result: Every Field at a Glance

A map of the whole record before we study each part in detail.

A Sampler Result is a bundle of fields. Some describe time, some describe size, some describe status, and some describe the request and the response. Here is a map. Later chapters examine each group carefully.

GroupFieldsQuestion it answers
IdentityLabel, thread name, timestampWhich step ran, who ran it and when?
TimingElapsed time, latency, connect time, idle timeHow long did it take and where was the time spent?
StatusResponse code, response message, success flag, failure messageDid it work and what did the server say?
SizeBytes received, bytes sent, headers size, body sizeHow much data moved?
ConcurrencyGroup threads, all threadsHow many users were active at that moment?
RequestSampler data, request headers, URL, cookiesWhat exactly was sent?
ResponseResponse data, response headers, data type, encodingWhat exactly came back?
StructureSub-results, sample count, error countWas this sample made of smaller samples?
VerdictsAssertion resultsWhich checks passed or failed?
9
groups of information in one record
1
record for each sampler run
Many
possible sub-results inside one record

Not every field is saved by default

The in-memory Sampler Result holds everything, but when results are written to a file, JMeter saves only a chosen set of fields. By default it saves a compact set that covers the essentials: timestamp, elapsed time, label, response code, response message, thread name, data type, success flag, failure message, bytes, sent bytes, group threads, all threads, URL, latency, idle time and connect time. Heavy fields such as response data, request headers and response headers are not saved unless you ask for them. This choice protects the file size and the memory of the load generator.

!
Common Mistake

Expecting to find response bodies in the results file after a long test, when the setting to save them was never turned on. Decide before the run which fields you will need for analysis, because you cannot recover data that was never saved.

5Timing Fields: Elapsed Time, Latency, Connect Time and Idle Time

Four clocks, each telling a different part of the story.

Timing is the heart of performance testing, and the Sampler Result carries several time measurements. Many people use only one, the elapsed time, and miss valuable information in the others.

Clock 1

Elapsed Time

The total time from just before the request is sent until the last byte of the response has been received. This is the number most reports call “response time” or “load time”.

Clock 2

Latency

The time from just before sending the request until the first byte of the response arrives. It shows how long the server took to start answering. In recent versions it includes the connect time.

Clock 3

Connect Time

The time taken to open the network connection, including the secure handshake for encrypted traffic. It is zero or very small when an existing connection is reused.

Clock 4

Idle Time

Time during which the thread was not sampling, for example while a timer paused it. It helps reconstruct the true rhythm of a user thread.

flowchart LR
    A["Request starts"] --> B["Connection opened: connect time"]
    B --> C["Request sent and server works"]
    C --> D["First byte arrives: latency ends"]
    D --> E["Rest of response downloads"]
    E --> F["Last byte arrives: elapsed time ends"]
        
FIG 2 — Where each clock starts and stops during one sample

Reading the clocks together

The clocks become powerful when read together. If the connect time is large, the problem is probably in the network path, in name resolution, or in the secure handshake. If connect time is small but latency is large, the server took a long time to start responding, which points to slow processing in the application or the database. If latency is small but the elapsed time is much larger, the server answered quickly but the response is large or the network is slow at carrying it. The gap between elapsed time and latency is roughly the download time.

What you seeMost likely meaningWhere to look first
High connect timeSlow connection set-up or secure handshakeNetwork path, load balancer, certificate settings, connection reuse
Low connect, high latencySlow server-side processingApplication code, database, external services
Low latency, high elapsedLarge or slowly delivered responseResponse size, compression, bandwidth, content delivery
All three smallHealthy and fastNothing to fix
Simple Analogy

Imagine ordering a pizza by phone. Connect time is how long it takes the shop to pick up your call. Latency is how long until the first sign of progress, such as the shop confirming the order. Elapsed time is how long until the pizza is at your door. A long wait can come from any of the three, and the fix depends on which one it is.

i
Practical Tip

When you report slow responses, quote the percentiles of elapsed time, but keep latency and connect time in your results file. They allow you to say not only that a request was slow, but also which part of the journey was slow, which is what developers need to fix it.

6Response Code and Response Message

What the server said, and what JMeter says when the server says nothing.

HTTP response codes

For web requests, the response code is the three-digit status the server returns, and the response message is the short text that goes with it, such as “OK” or “Not Found”. Codes in the two hundreds mean success. Codes in the three hundreds mean redirection. Codes in the four hundreds mean the client made a mistake. Codes in the five hundreds mean the server failed. The HTTP sampler treats the four-hundred and five-hundred families as failed samples by default, unless an assertion or setting says otherwise.

CodeMessageMeaning in a load test
200OKRequest succeeded, but the content still needs checking
201CreatedA new item was created, common after posting data
302FoundRedirect, often during log-in flows
400Bad RequestThe request was malformed, often a script or data problem
401UnauthorizedMissing or expired credentials, often an expired token
403ForbiddenAccess denied, may be a security rule blocking the load
404Not FoundWrong address or missing data
429Too Many RequestsRate limiting is active and is slowing your test
500Internal Server ErrorThe application failed while processing
502 / 503 / 504Gateway or service errorsA proxy, load balancer or backend is overloaded or unreachable

When the response code is not a number

Sometimes the request never reaches a normal server answer. The connection may be refused, the name may not be found, the secure handshake may fail, or the response may time out. In these cases, JMeter fills the response code with a text that starts with “Non HTTP response code” followed by the name of the technical error. The response message then starts with “Non HTTP response message” followed by details. These entries are very valuable, because they tell you that the problem happened before the application could answer.

Case 1

Connection refused

Nothing is listening at that address and port. The server may be down, or a firewall or load balancer is rejecting connections at the thread count you reached.

Case 2

Unknown host

The name could not be resolved. Check the address, the name server and any local host settings on the load generator.

Case 3

Read or connect timeout

The server accepted the request but did not answer in time, or the connection could not be opened in time. This often signals saturation.

Case 4

Secure handshake failure

The encrypted connection could not be established, often because of certificate trust, protocol versions or server overload.

!
Common Mistake

Counting only the numeric error codes and ignoring the text codes. Reports that group errors by number may show “a few errors” while thousands of requests failed with connection or timeout problems. Always group by the full response code text, so no failure family is hidden.

Simple Analogy

A numeric code is like a shop assistant who answers your question, even if the answer is “sorry, we are out of stock”. A non-HTTP code is like walking up to a shop with a locked door, a dead phone line or a missing address. In the first case you got an answer. In the second case you never reached anyone.

7The Success Flag, Assertions and Failure Messages

A request can return a happy status code and still be a failure. The success flag exists to tell the truth.

The Sampler Result carries a success flag, a simple yes or no that says whether the sample passed. The sampler sets an initial value based on its own rules, such as the status code family. Then every assertion attached to the sample gets a chance to change it. If any assertion fails, the final success flag becomes false and a failure message is attached to explain why.

Why status codes alone are not enough

Many modern applications return a normal success code even when the business action failed. A log-in page may return a normal page with the words “wrong password”. A search may return a normal page with the words “no results because of an internal error”. A payment service may return a success code with an error message inside the data. If you only trust the status code, all of these appear green, and your report shows a perfect error rate while real users are suffering.

Assertion

Response Assertion

Checks text, code, message, headers or the address of the sample against patterns. The most common and the most flexible check.

Assertion

Duration Assertion

Fails a sample whose elapsed time is longer than a limit you set. Useful for enforcing an agreed response time target.

Assertion

Size Assertion

Checks that the response size is equal to, larger than or smaller than a number of bytes. Helps detect empty or truncated responses.

Assertion

JSON and XML Assertions

Check that structured responses contain the right fields and values, instead of searching raw text.

flowchart TD
    A["Sampler sets the first success value from its own rules"] --> B["Assertion 1 checks the result"]
    B --> C["Assertion 2 checks the result"]
    C --> D{"Did any assertion fail?"}
    D -->|"Yes"| E["Success flag becomes false and a failure message is stored"]
    D -->|"No"| F["Success flag stays as it was"]
        
FIG 3 — How assertions decide the final success flag

Balancing strictness and cost

Assertions cost CPU time, because JMeter must search or parse each response. A very large number of heavy assertions can slow down the load generator and distort the timings. The art is to choose a few checks that prove the business action worked, such as one unique word on the confirmation page, rather than scanning the whole body for many patterns. A well-chosen assertion is cheap and powerful.

i
Practical Tip

For every important step, such as log-in, search and checkout, add at least one assertion that checks a sign of real success, such as a welcome name or an order number. Without it, you are measuring how fast the application can return an error page.

Example: hidden failures behind a 200

A team load-tested a booking page and saw a clean report with zero errors. After they added a check for the booking reference, the error rate jumped to thirty percent. The server had been returning a normal page that said “service busy” under load. The first report had been green only because nothing was checking the content.

Ignore status and non-failing assertions

The Response Assertion has an option called ignore status, which tells it to ignore the failure already caused by the status code, so that a deliberate error response, such as a planned 404 in a negative test, can be counted as a pass. Use this carefully and only for tests where the error is the expected result.

8Size Fields: Bytes, Sent Bytes, Headers Size and Body Size

How much data moved, and why that explains so many slow requests.

The Sampler Result records the amount of data in both directions. These numbers help you understand bandwidth use, spot unexpectedly large responses, and explain why one request is slower than another even though the server worked equally hard.

Size 1

Bytes (Received)

The total size of the response, including the headers and the body. This is the main size number in reports.

Size 2

Sent Bytes

The total size of what JMeter sent in the request, including headers and any posted data.

Size 3

Headers Size

The part of the response that is made of headers. Large cookies and many headers can add surprising weight to every request.

Size 4

Body Size

The part of the response that is the actual content, such as the page or the data.

Using sizes to find problems

Sizes are a quick sanity check. A page that normally weighs two hundred kilobytes and suddenly weighs two kilobytes under load is almost certainly an error page, even if the status code looks normal. A response that is much larger than expected may indicate missing compression or a data query that returns too many rows. Total received bytes divided by the test time gives the network throughput, which tells you whether the network card or the link to the server could be the limit.

ObservationPossible reasonAction
Response size suddenly much smallerError or fallback page returned with a normal codeAdd a content or size assertion
Response size much larger than expectedCompression off, too many rows returned, debug data includedCheck headers and the query behind the page
Large headers sizeBig cookies or many custom headersReview what the application sets on every response
Throughput stops growing but CPU is idleNetwork bandwidth reachedCheck link capacity and the generator network card
Simple Analogy

Size is like the weight of a parcel. A courier can be fast and still take longer to deliver a heavy parcel, because carrying it takes more effort. If a parcel that should weigh one kilogram arrives weighing ten grams, you immediately suspect that something important is missing from the box.

i
Practical Tip

Keep a record of the normal response size for each key step in your test plan. When a test shows a different size, the difference is often the first and fastest clue that something has changed in the application.

9Identity and Concurrency Fields: Label, Thread Name, Timestamp and Active Threads

Who ran it, when it ran and how busy the test was at that moment.

Label

The label is the name of the sample. By default it is the name of the sampler in your test plan. The label is the main key used to group samples in every summary and graph, so a clear and stable naming scheme is one of the most useful habits in performance testing. Chapter 18 treats naming in detail.

Thread name

The thread name combines the name of the thread group and the number of the thread, such as “Shoppers 1-37”. It tells you which virtual user produced the sample. When one user keeps failing while others succeed, the thread name lets you look at that one user’s whole journey and find what was special about it, such as bad test data.

Timestamp

The timestamp records the moment of the sample as a number of milliseconds since the first of January 1970 in universal time. It is the basis of every graph that has time on the horizontal axis. Because all load generators should use synchronised clocks, timestamps from several machines can be placed on one common timeline.

Active threads

Two fields record how busy the test was at the moment of the sample. Group threads is the number of active threads in the same thread group. All threads is the number of active threads in the whole test, across all groups on that machine. These fields let you plot response time against the number of active users, which is exactly the graph you need to find the point where the system begins to struggle.

flowchart LR
    A["Samples with timestamp and active threads"] --> B["Group by time"]
    B --> C["Response time over time"]
    B --> D["Throughput over time"]
    B --> E["Active threads over time"]
    C --> F["Combined view: how speed changes as users grow"]
    D --> F
    E --> F
        
FIG 4 — Identity and concurrency fields make the timeline graphs possible
!
Distributed Test Reminder

In a test with several workers, the active thread numbers in each sample describe only the machine that ran the sample. To find the total number of active users in the whole test, you must combine the numbers from all workers at the same moment, or use a tool that does this for you.

Example: spotting a broken test account

A tester saw a steady five percent failure rate. Grouping failed samples by thread name showed that almost all failures belonged to three threads. Those three threads had been given test accounts that were locked. Fixing the data removed the failures, and the application had never been at fault.

10The Request Side: Sampler Data, Request Headers, URL and Cookies

The part of the record that proves exactly what JMeter sent.

When a response looks wrong, the first question is always “what did we really send?”. The Sampler Result keeps the answer, as long as it was kept in memory or saved. The request-side fields are your evidence.

Field 1

Sampler Data

A description of the request as sent, such as the method, the address and the body that was posted. It shows the real values after variables have been replaced.

Field 2

Request Headers

The headers that were sent, such as content type, authorisation and accepted formats. Missing or wrong headers cause many mysterious failures.

Field 3

URL

The full address that was called, including query parameters. Useful for checking that variables were replaced correctly.

Field 4

Cookies

The cookies that were sent with the request. They show whether the thread kept its session or started afresh.

The most common discovery

The most frequent discovery when reading the request side is that a variable was not replaced. The test plan said to send a token, but the request shows the text of the variable name instead of its value. This means the extractor that should have captured the token did not find it in the previous response. Without the request-side evidence, the failure would look like a server problem. With it, the cause is clear within seconds.

1

Open the failing sample

Look at the request side first: the address, the headers and the body that were really sent.

2

Compare with what you expected

Check that every variable shows a real value, that the content type is right and that cookies are present when they should be.

3

Trace backwards

If a value is missing, open the previous sample and its response to see why the extractor failed to capture it.

4

Fix and repeat

Correct the extractor or the data, and run again with a single thread to confirm before returning to a full test.

!
Privacy Note

Request headers and bodies often hold passwords, tokens and personal data. They are valuable for debugging and dangerous in shared files. Chapter 20 explains how to handle this safely.

11The Response Side: Response Data, Response Headers, Data Type and Encoding

What came back, and how JMeter understands it.

Response data

The response data is the body of the answer: a page, a data message, a file. JMeter keeps it in memory while extractors and assertions work on it. For text answers it can be searched with patterns. For binary answers, such as images or documents, JMeter keeps the bytes but does not try to read them as text. Response data is often the biggest piece of a Sampler Result, and it is the biggest reason that results consume memory.

Response headers

The response headers are the extra information the server sends with its answer: content type, content length, cache rules, cookies to set, and server identification. Extractors can read them to capture values, and assertions can check them. They are also very useful for diagnosing caching, compression and security settings.

Data type and encoding

The data type tells whether the response is treated as text or as binary. The encoding tells JMeter which character set to use when it turns bytes into text. If the encoding is wrong, accented letters and many non-English characters appear as strange symbols, and text checks may fail even though the server answered correctly. If an assertion on a non-English page fails mysteriously, check the encoding first.

FieldWhat it holdsTypical useCost
Response dataThe body of the answerExtractors, assertions, debuggingHigh memory use
Response headersHeader lines from the serverCaching, cookies, security checksLow
Data typeText or binaryDecides how the body is handledNone
EncodingCharacter set of the textCorrect reading of non-English textNone
Simple Analogy

Response data is the letter inside an envelope. Response headers are the writing on the outside of the envelope: sender, date, handling instructions. Encoding is the language the letter was written in. If you read a Hindi letter as if it were French, the words look like nonsense even though the letter is perfectly fine.

i
Practical Tip

During script development, keep response data and headers so you can study them. During large load runs, turn off saving them, and rely on assertions to detect failures, so that the load generator keeps its memory for the threads.

12Sub-Results: Redirects, Embedded Resources and Transactions

Sometimes one Sampler Result contains smaller ones inside it.

A single Sampler Result can have sub-results, which are smaller results nested inside a parent result. This happens in three common situations, and each of them changes how you read your numbers.

Case 1

Redirect chains

When the server answers with a redirect and JMeter is set to follow it, each step of the chain can be stored as a sub-result under the main one. The parent shows the final answer, and the children show the journey.

Case 2

Embedded resources

When the sampler is set to retrieve images, scripts and styles that a page refers to, each of those downloads becomes a sub-result of the page sample. This makes the page time include the downloads.

Case 3

Transaction controllers

A transaction controller groups several samplers into one business step, such as “Place order”. It can produce a parent result whose time is the total of the steps inside.

flowchart TD
    P["Parent sample: Checkout page"] --> C1["Sub-result: main HTML"]
    P --> C2["Sub-result: style file"]
    P --> C3["Sub-result: script file"]
    P --> C4["Sub-result: product image"]
        
FIG 5 — A parent Sampler Result with sub-results for each downloaded resource

Why this matters for your numbers

If you group several steps in a transaction and also keep the individual steps in your summary, then the same time is counted twice, once inside the child and once inside the parent. A report that adds everything together would show inflated throughput and counts. Most reports solve this by showing only the parent, or by letting you choose whether to include the sub-samples. Know which one your report uses before you compare tests.

The transaction controller options

The transaction controller has an option to generate a parent sample. When it is on, the group appears as one result with the others hidden inside. When it is off, the group’s total appears as an extra sample next to the individual samples. Another option decides whether the pauses from timers and the work of pre-processors and post-processors inside the group are counted in the total. Choose deliberately: counting the pauses gives the full user-experienced time of a journey, while leaving them out gives the pure system time.

SettingWhen onWhen off
Generate parent sampleOne combined result with children insideIndividual results plus an extra total result
Include timer and processor timeTotal includes pauses and script workTotal is only the measured request time
Retrieve embedded resourcesPage time includes the downloadsOnly the main document is timed
!
Common Mistake

Comparing a test that retrieved embedded resources with one that did not, and concluding that the application became slower. The difference may be only the extra downloads inside the page time. Keep these settings identical across tests you want to compare.

Simple Analogy

A sub-result is like the parts of a journey inside a travel booking. The parent is “trip from home to the hotel”, and the children are the taxi, the train and the walk. You can talk about the whole trip or about each part, but you must not add the whole trip and its parts together, or you would count the same hours twice.

13Reading the Sampler Result in View Results Tree

The debugging window where most people first meet the record.

The View Results Tree listener shows each sample as an entry on the left. Selecting an entry shows its details on the right, split into tabs. The tab named Sampler Result is the one that displays the summary of the record, and the other tabs show the request and the response in detail.

Tab 1

Sampler Result

The summary: thread name, start time, load time, connect time, latency, sizes, counts, data type, response code, response message and response headers.

Tab 2

Request

What was sent: the request line, the headers and the body, with variables already replaced by their values.

Tab 3

Response data

What came back, shown as text, as formatted markup, as a rendered page, as structured data or as a result of a test pattern, depending on the viewer you pick.

A reliable reading routine

1

Check the colour and the status

Failed samples are marked in red. Open the Sampler Result tab and read the response code and message first.

2

Read the timings

Compare connect time, latency and load time to see which part of the journey was slow.

3

Open the request

Confirm the address, headers and body. Look for unreplaced variables and wrong content types.

4

Open the response

Read the body. Does it look like the expected page or like an error message that returned with a normal status?

5

Check assertion results

If a sample failed with a normal code, the failure message tells you which assertion judged it a failure and why.

!
Important

View Results Tree keeps every result in memory, including full request and response data. Use it only for debugging with a handful of threads. Leaving it enabled during a real load test is one of the fastest ways to fill the memory of a load generator and ruin a run.

i
Practical Tip

For long debugging sessions, configure the listener to display only errors, so the list does not fill with thousands of green entries. Searching for a failure among green results wastes time.

14Using the Sampler Result Inside the Test: Extractors, Assertions and Scripts

The result is not only for reports. The test itself reads it to make decisions.

While a test runs, other elements read the Sampler Result of the sampler they belong to, and use it to drive the next steps. This is how a script copes with changing session tokens, dynamic identifiers and conditional journeys.

Extractors read fields from the result

Extractors are post-processors that search the result and store what they find in variables. A Regular Expression Extractor, a JSON Extractor, an XPath Extractor and a Boundary Extractor can all read the response body. Many of them can also be told to read other fields of the result: the response headers, the request headers, the address, the response code or the response message. This choice is called the field to check, and it is the way to capture a token from a header or the status code into a variable for later decisions.

Scope: main sample and sub-samples

When a result has sub-results, such as embedded resources, an extractor or assertion needs to know which part to read. The scope setting offers choices: the main sample only, the sub-samples only, both, or the value of a variable. The default is the main sample only. If a value you need appears in a sub-sample, such as a redirect step, but your extractor looks only at the main sample, the extractor will quietly find nothing.

ElementWhat it reads from the resultWhat it does with it
Regular Expression ExtractorBody, headers, address, code or messageStores matched text in a variable
JSON ExtractorBody that holds structured dataStores values selected by a path
Response AssertionBody, headers, code, message, address or request dataPasses or fails the sample
Duration AssertionElapsed timeFails the sample if too slow
Script post-processorThe whole previous result objectCustom logic, such as computing or deciding

Script elements and the previous result

Script-based elements in JMeter can reach the whole Sampler Result of the sampler that just ran, through an object commonly called the previous result. From there a script can read any field: the code, the timings, the sizes, the headers. It can also change the result, for example to mark a sample as failed for a business reason, or to change the label. This is powerful, but it should be used sparingly, because scripts cost CPU time and can slow the generator under high thread counts.

i
Practical Tip

Prefer the built-in extractors and assertions for everyday work. They are faster, easier to maintain and easier to explain to others. Keep scripts for logic that no built-in element can express.

Example: reading a token from a header

A secure service returns an access token in a response header instead of the body. The team uses an extractor with the field to check set to response headers. The token is stored in a variable that belongs to the thread, and the next request sends it back. Without this setting, the extractor would search the body, find nothing and every later request would fail.

Example: conditional journey on a status code

A script reads the response code of the log-in step. If the code shows that the session expired, the thread repeats the log-in. Otherwise it continues to the next step. The decision uses a field of the Sampler Result to make the test behave like a real user who logs in again.

15Saving Sampler Results: JTL Files, CSV, XML and Save Settings

Choosing what to keep decides what you can learn afterwards.

During a real test, results should be written to a file as they are produced. This file is commonly called a JTL file. The command-line option for the results file is the standard way to produce it in non-GUI mode. After the test, tools and the report generator read this file to produce tables and graphs.

CSV or XML

JMeter can save results as comma-separated rows or as XML records. The CSV format is compact and fast, and it is the default in recent versions and the one most analysis tools expect. The XML format can hold full request and response data and nested sub-results with more structure, but it is much larger and slower to write. For load tests, CSV with a carefully chosen set of fields is usually the right choice. XML is useful for short debugging runs where you need every detail.

CSV format

  • Small files and fast writing
  • Opens in spreadsheet and analysis tools
  • Works directly with the HTML report generator
  • Ideal for long and heavy tests

XML format

  • Much larger files
  • More memory and CPU to write
  • Harder to analyse at scale
  • Best kept for short debugging runs

Choosing which fields to save

The set of saved fields is controlled by settings in the JMeter properties file or in the configuration window of a listener. The defaults cover the essentials. You can add fields you need and remove those you do not. Adding the response data or the headers makes files much larger, and the load generator must hold and write all that data. Saving only failed samples with full details, while saving a light record for every sample, is a common compromise.

Keep

Essential timing and status

Timestamp, elapsed time, label, response code, response message, success flag and failure message. Almost every analysis needs these.

Keep

Detail timings and sizes

Latency, connect time, idle time, bytes and sent bytes. They explain where time and bandwidth went.

Keep

Concurrency fields

Thread name, group threads and all threads. They connect speed to the number of active users.

Use with care

Bodies and headers

Response data and headers are heavy and can hold sensitive data. Save them for failures or short runs, not for every sample.

!
Common Mistake

Overwriting the results file of a previous run, or appending a new test to an old file. Both ruin the analysis. Give every run its own results file and folder, named with the date and a short description of the test.

i
Practical Tip

Add a header row to CSV files and keep the same set of fields across tests. Consistent files let you compare tests with the same tools and the same scripts, and they let new team members understand old results without guessing.

16From Samples to Statistics: How Reports Use Sampler Results

Every number in a report is a calculation over many small records.

Listeners like the Summary Report, the Aggregate Report and the HTML dashboard take thousands of Sampler Results and group them, usually by label. For each group they calculate familiar statistics. Knowing exactly which field feeds which statistic lets you judge whether a number deserves your trust.

StatisticCalculated fromHow to read it
SamplesCount of results per labelHow many times the step ran
AverageMean of elapsed timeA rough centre, easily pulled by slow outliers
MedianMiddle value of elapsed timeWhat a typical request experienced
90, 95, 99 percent linesElapsed time at that rankWhat the slowest tenth, twentieth or hundredth experienced
Minimum and maximumLowest and highest elapsed timeThe extremes, useful for spotting spikes
Error percentShare of results with the success flag falseHow often the step failed
ThroughputCount of results divided by test timeHow many requests were completed per second
Received and sent rateBytes fields divided by test timeHow much network traffic was used

Percentiles tell the truth about slow users

The average hides the tail. If ninety-five requests take one second and five take twenty seconds, the average is nearly two seconds, but one in twenty users waited twenty seconds. The ninety-fifth and ninety-ninth percentile lines expose this. Always read the percentile lines before the average, and always report them next to it.

“A report is only as honest as the Sampler Results beneath it.”

The garbage-in rule

Statistics cannot fix bad samples. If the success flag is wrong because nobody asserted on content, the error percentage is wrong. If the label is unstable, the groups are wrong. If the timestamp is not synchronised across machines, the timeline is wrong. If ramp-up samples are mixed with steady-state samples, the averages are wrong. Check the quality of the samples before you believe the summary.

flowchart LR
    A["Thousands of Sampler Results"] --> B["Group by label"]
    B --> C["Filter out ramp-up and ramp-down periods"]
    C --> D["Calculate average, percentiles, errors, throughput"]
    D --> E["Tables and graphs in the report"]
        
FIG 6 — How a report turns individual samples into statistics
i
Practical Tip

The HTML report generator can filter which labels and which time range are included. Use it to exclude the ramp-up and ramp-down, so the figures describe the steady period, and to exclude helper samplers, such as set-up steps, that do not represent user actions.

17The Cost of Sampler Results: Memory, CPU and Disk on the Load Generator

Every result has a price, and a heavy test pays it thousands of times per second.

It is easy to forget that each Sampler Result is a real object living in the memory of the load generator. With a few threads this is invisible. With hundreds of threads sending many requests per second, the total weight becomes significant, and the cost of keeping, processing and writing results can slow the test tool itself.

Cost 1

Memory

Response bodies, headers and request data are held until all processors and listeners finish. Large bodies multiplied by many threads fill the heap quickly.

Cost 2

CPU

Assertions, extractors and scripts read and search the result. Heavy patterns on large bodies can burn a lot of processor time.

Cost 3

Disk

Writing every sample to a file takes time and space. Saving full bodies can fill a disk during a long test.

Cost 4

Network

In distributed tests, results travel from each worker to the controller. Heavy result traffic can overload the controller or its network link.

How to keep the cost low

1

Run without the graphical interface

Use command-line mode for real tests, and write results to a file. Graphical listeners keep results in memory and draw them continuously.

2

Remove debugging listeners

Disable or delete View Results Tree and similar listeners before load tests. Keep only a light file writer.

3

Save lean records

Save the essential fields for every sample and keep bodies and headers for failures only, or for short debug runs.

4

Use cheap checks

Prefer simple, targeted assertions to scanning large bodies with complicated patterns.

5

Size the heap and watch the generator

Give the JMeter process enough memory, and monitor its CPU, memory and garbage collection during every run.

!
Why This Affects Accuracy

If the load generator is starved of memory or processor time, requests are delayed inside JMeter itself, and the elapsed times in the Sampler Results include delays that the application never caused. A heavy result-handling set-up can therefore make a healthy application look slow.

Simple Analogy

Imagine a delivery driver who must stop at every house to write a long report before moving on. The more detailed the report, the fewer parcels he delivers per hour, and the slower every delivery looks to the customer. Lean records keep the driver moving.

18Design Patterns for Labels and Result Naming

A good name today saves hours of confusion when you read results next month.

The label is the key that groups samples. Every table and graph in your report is built on it. A careful naming scheme makes reports readable and comparable. A careless one produces thousands of useless groups and makes trends invisible.

Pattern 1: order and readability

Start labels with a number that shows the order of the step in the journey, followed by a short meaningful name, such as “01 Open home page”, “02 Search product” and “03 Add to cart”. Reports then sort in the natural order of the user journey, and anyone can read them without opening the test plan.

Pattern 2: stable labels, never dynamic ones

Never put changing values, such as user identifiers or order numbers, in a label. If the label contains a variable that changes on every request, each sample creates its own group. A test with a hundred thousand requests then shows a hundred thousand rows in the report, and the load generator and the report tool both choke. Put changing values in the request, not in the name.

Pattern 3: one name per business action

Give each business action one clear name, and keep that name identical across tests and across script versions. When names change, history is lost, and you cannot compare today’s result with last month’s.

Pattern 4: separate main steps from helper steps

Some samplers are only technical helpers, such as fetching a token or setting up data. Give them a clear prefix so you can exclude them from user-facing statistics. Otherwise, your average response time mixes real user steps with internal helpers, and the average no longer describes the user experience.

Pattern 5: group embedded resources sensibly

When pages download many images and scripts, those sub-results can flood the report with rows. Use the option that places resources under their parent, or use a naming pattern that groups them, so the report focuses on business steps.

Label styleExampleResult
Numbered and clear03 Add to cartSorted, readable, comparable across tests
Default and vagueHTTP Request 7Meaningless to readers, easy to confuse
Contains dynamic valueOpen order 928374One group per request, huge reports, no useful statistics
Helper prefixedZ Get tokenEasy to exclude from user statistics
i
Practical Tip

Agree on a naming standard with your team before writing scripts, and put it in a short document. Consistent names turn a folder of old test results into a useful history that shows how the application changes over time.

19Sampler Results in Distributed Tests and Live Dashboards

Results travel, and the way they travel changes what you can see.

Results from many workers

In a distributed test, each worker machine runs the test plan and creates its own Sampler Results. These results are sent back to the controller, which collects them into one stream for the listeners and the results file. This means that the controller handles the results of every worker, and under high load it can become a bottleneck if the results are heavy or very numerous.

Sending modes

JMeter lets you choose how workers send results to the controller. The standard mode sends each sample as soon as it is ready, which gives the most live view but costs the most network and processing. Other modes send samples in batches, send summarised statistics instead of every sample, remove heavy data such as response bodies before sending, or store samples on disk and send them in the background. The right choice depends on your test size. A light mode such as batching or stripping heavy data is usually recommended for large tests, while the standard mode suits small ones.

flowchart TD
    W1["Worker 1: creates Sampler Results"] --> S["Result sending mode: standard, batch or lighter"]
    W2["Worker 2: creates Sampler Results"] --> S
    W3["Worker 3: creates Sampler Results"] --> S
    S --> C["Controller: collects all results"]
    C --> F["Results file and listeners"]
        
FIG 7 — Results flow from workers to the controller in distributed mode

Live dashboards through a backend listener

The Backend Listener sends aggregated information from the Sampler Results to an external metrics database while the test is running. Typical numbers sent are the count of samples, the average and percentile response times, the error counts and the active thread counts, grouped by label and by time interval. A dashboard tool then draws live graphs. This lets you watch the test as it happens, correlate it with server metrics on the same screen, and stop the test early if something is clearly wrong.

ApproachStrengthWeakness
Results file and later reportComplete record, easy to repeat analysisYou see the story only after the test
Backend listener and live dashboardLive view next to server metricsAggregated data, not every raw sample
Both togetherLive view plus a complete recordSlightly more set-up and a little more load
i
Practical Tip

For serious tests, use both: a lean results file as the permanent record and a backend listener for the live dashboard. The file keeps the evidence for later analysis, and the dashboard gives you the chance to react while the test is still running.

!
Clock Reminder

Keep the clocks of the controller, the workers and the servers synchronised. Without it, timestamps in the Sampler Results do not line up with server metrics, and a graph that should show cause and effect shows a confusing gap.

20Security and Privacy of Result Data

A Sampler Result can contain the exact secrets your application protects.

Because a Sampler Result may hold the full request and response, it can contain passwords, access tokens, cookies, personal details and business data. A results file or a screenshot from the debugging window is therefore sensitive material, even if the test used only test accounts. The risk is real: result files are often attached to emails, uploaded to shared drives and pasted into tickets.

Risk 1

Credentials in requests

Log-in steps send usernames and passwords. Request headers carry tokens. Saving these fields places secrets in the file.

Risk 2

Personal data in responses

Responses may contain names, addresses, account numbers or messages. If the test environment holds copied production data, the risk is higher.

Risk 3

Session cookies

Saved cookies and tokens could be reused to impersonate the test users if the environment is reachable.

Risk 4

Shared evidence

Screenshots, results files and reports passed around a company may reach people who should not see the content.

Protective habits

1

Use synthetic data

Test with fake accounts and generated data. Never run load tests with real customer details.

2

Save only what you need

Do not save request headers, response headers or bodies for every sample. The less you store, the less can leak.

3

Protect and expire result files

Store files in access-controlled locations, and delete them when they are no longer needed.

4

Clean before sharing

Before sending evidence outside the test team, remove or mask secrets and personal values from screenshots and extracts.

5

Rotate test credentials

Change test passwords and tokens after sharing evidence or after a large test, so that anything that leaked becomes useless.

!
Important

Treat a results file that contains request and response data like a password file. If it would be a problem for an outsider to read the content of your application’s real traffic, it is a problem if they read this file.

21Anti-patterns That Corrupt Your Results

Mistakes that make the Sampler Results lie, or make you misread them.

ANTI-PATTERN-01 Avoid
Problem

The team trusts the status code alone, with no content check on any important step.

Why It’s Harmful

Applications often return a normal code with an error message in the content. The success flag stays true, the error rate shows zero, and real failures stay hidden until users complain.

Correct Approach

Add a cheap assertion to every key step that proves the business action worked, such as an order number or a welcome message.

ANTI-PATTERN-02 Avoid
Problem

View Results Tree and other heavy listeners stay enabled during a load test.

Why It’s Harmful

Memory fills with full requests and responses, garbage collection freezes threads, and the elapsed times include delays from the test tool itself.

Correct Approach

Use debugging listeners only with a few threads. For load tests, run in command-line mode and write a lean results file.

ANTI-PATTERN-03 Avoid
Problem

Dynamic values such as user identifiers or order numbers are placed in sampler labels.

Why It’s Harmful

Each request becomes its own group, reports explode in size, memory is wasted on thousands of group records, and no meaningful statistics exist for any step.

Correct Approach

Use stable, numbered labels. Keep changing values in the request, not in the name.

ANTI-PATTERN-04 Avoid
Problem

The report uses the average response time as the main figure and nothing else.

Why It’s Harmful

Slow outliers hide inside the average. A step with a healthy average may still leave one in twenty users waiting many seconds.

Correct Approach

Report the median and the ninetieth, ninety-fifth and ninety-ninth percentile lines, together with the error percent and throughput.

ANTI-PATTERN-05 Avoid
Problem

Ramp-up samples, steady-state samples and helper-step samples are mixed in one summary.

Why It’s Harmful

Ramp-up results describe a changing load, and helper steps do not represent user actions. The mix gives a figure that describes nothing real.

Correct Approach

Filter the report to the steady period and exclude helper samples, using clear labels and the report filters.

ANTI-PATTERN-06 Avoid
Problem

Result files containing request and response data are emailed and uploaded without cleaning.

Why It’s Harmful

Passwords, tokens and personal data leak to people who should not see them, and the test turns into a security incident.

Correct Approach

Save lean records, store files in protected places, mask evidence before sharing, and rotate test credentials after large tests.

22Best Practices and Real-World Examples

A checklist you can apply tomorrow, and four stories that show it working.

Best-practice checklist

1

Inspect real samples first

Run with one or two threads and read a few full Sampler Results before any large test.

2

Assert on content

Make sure every key step has a cheap content check, so the success flag means something.

3

Name labels carefully

Use numbered, stable labels and a clear prefix for helper steps.

4

Save lean, plan your fields

Choose the saved fields before the run. Use CSV, and keep bodies and headers for failures or debug runs.

5

Read all timing clocks

Keep connect time and latency in the file and use them to locate where time was spent.

6

Report percentiles and steady state

Filter out ramp periods, and report percentiles with errors and throughput.

7

Protect the generator and the data

Run in command-line mode, watch the generator’s health and protect result files.

8

Keep history

Name result files by date and test type, keep the same fields across runs, and compare releases over time.

Real-world stories

Retail checkout with hidden failures

A retailer saw a clean report before a sale. Opening individual Sampler Results showed that checkout pages returned a normal code with a message about a busy payment service. After the team added a content check on the order confirmation, the true error rate was visible, the payment service was fixed, and the sale ran smoothly.

Slow log-in explained by connect time

A bank’s log-in looked slow in tests. Latency was fine, but connect time was high. The cause was a secure handshake repeated on every request because connection reuse was off in the test configuration. Fixing the setting cut the elapsed time in half, and the application code had not been the problem.

Memory crash from saved bodies

An engineer ran a four-hour test with response bodies saved for every sample. After two hours the load generator ran out of memory and the test stopped. Switching to a lean result file with bodies saved only for failures made the same test finish with plenty of headroom.

One broken thread among hundreds

A test showed a small but steady error rate. Grouping failed Sampler Results by thread name revealed that only a few threads were failing, all with locked test accounts. Cleaning the test data removed the errors, saving the team from chasing a problem that did not exist in the application.

23Sampler Results for Non-HTTP Samplers

The same record, filled in differently for databases, messages, sockets and scripts.

Most examples in this guide use web requests, but JMeter can test many other things: database queries, message queues, file transfers, directory services, raw network sockets and custom scripts. All of them create Sampler Results with the same set of fields. What changes is how each sampler fills those fields. Understanding these differences stops you from misreading results when you leave the world of web pages.

Sampler

Database query sampler

The elapsed time covers running the query and fetching the result. The response data holds the returned rows as text. There is no web status code, so the sampler uses its own simple success or failure values.

Sampler

Messaging samplers

Sending a message and waiting for a reply are measured as separate kinds of samples. The elapsed time may show only the time to hand the message to the broker, not the time until a consumer processed it.

Sampler

Raw network sampler

Sends bytes over a connection and reads until a chosen end condition or a timeout. The elapsed time includes the wait for that end condition, so a wrong end setting inflates the time.

Sampler

Script-based sampler

A script decides what to measure and can fill the result fields itself: the label, the status, the data and the success flag. It gives freedom, but also puts the responsibility for correct measurement on you.

Helper

Debug sampler

Creates a result whose data lists the current variables and properties. It is a handy way to inspect what a thread holds at a given moment, but it should be removed or disabled before real load.

Helper

Flow control steps

Steps that only change the flow of the test, such as skipping to the next loop, are not real requests and do not produce results of their own.

What to check when you leave HTTP

1

Find out what the elapsed time covers

Read the documentation of the sampler to learn exactly where the clock starts and stops. A database sampler and a messaging sampler measure very different things under the same name.

2

Do not expect latency and connect time to mean the same

For many non-web samplers, connect time is zero or latency equals the elapsed time. That is normal, not an error.

3

Define success yourself

Without an HTTP status family, the default success rule may be weak. Add assertions on the returned data, such as a number of rows or a specific field value.

4

Watch the size of returned data

A query that returns a huge number of rows costs memory in the result and time to transfer. Limit rows in the test query to what a real user would receive.

5

Name samples by business action

“Load customer profile” is a better label than the name of a table or queue. Reports should speak the language of the business.

!
Common Mistake

Measuring only the time to send a message and reporting it as the time to complete a business process. The user waits for the whole process, not just the hand-over. If the real process includes a consumer, design a test that measures the time until the effect is visible.

Simple Analogy

Posting a letter and receiving the reply are two different events. A stopwatch that stops when the letter drops into the postbox tells you how fast you walked to the postbox, not how fast the other person answered. The sampler’s own definition of “done” decides what your stopwatch measures.

Example: database sample with a weak success rule

A team tested a reporting query and saw all samples green with fast times. Later they found that under load the query returned zero rows because of a timeout in a lower layer, but the sampler treated an empty result as success. Adding a check on the minimum number of rows exposed the failures.

24Advanced Result Analysis: Asking Better Questions of the Data

A results file is a small database. The value comes from the questions you ask it.

Once a test is finished, the results file holds the full story of the run in thousands or millions of rows. Standard reports answer the usual questions, but expert engineers go further. They slice the data by time, by label, by thread and by response code to answer sharper questions. The following ideas turn raw Sampler Results into real insight.

QuestionFields to combineWhat you learn
When did the slowdown start?Timestamp with elapsed time per time intervalThe exact moment and the load level at that moment
At what user count does speed degrade?All threads with elapsed time percentilesThe knee, where response time begins to climb
Which step is the weakest?Label with percentiles and error percentThe step that deserves developer time first
Are errors random or clustered?Timestamp, thread name, response codeWhether failures link to time, user or load
Is the network or the server slow?Connect time, latency, elapsed timeWhich part of the journey takes the time
Are responses suspiciously small?Bytes with label and success flagHidden error pages that pass as success
Did this release get slower?Same label across two result filesA before-and-after comparison on identical steps

Slice by time

Group samples into small time buckets, such as every ten or thirty seconds, and calculate the percentiles, the error count and the throughput for each bucket. The result is a timeline that shows how the system behaved during the test, rather than one average for the whole run. Events such as garbage collection pauses, scheduled jobs, cache expiry and auto-scaling appear as spikes or steps on this timeline, and you can match them with server logs.

Slice by error type

Group failed samples by the full response code text and the failure message. A report that says “five percent errors” is far less useful than one that says “three percent connection timeouts, one percent service unavailable and one percent failed content checks”. Each type points to a different cause and a different owner.

Compare runs, not just numbers

The strongest use of results is comparison. Run the same test against the old and the new version and compare the percentiles per label. Make sure the settings are identical: the same thread counts, the same ramp-up, the same data and the same labels. A single run can be unlucky, because networks, caches and shared environments vary. Repeat important tests several times, and treat differences smaller than the natural variation between identical runs as noise.

i
Practical Tip

Run a test three times before you announce that a release is faster or slower. If the three runs give very different figures, the environment is unstable, and the first job is to stabilise it, not to analyse the application.

Satisfaction scores

The HTML report includes a satisfaction score built from elapsed times, often called an Apdex score. It uses two thresholds: a lower one under which a response is called satisfying, and a higher one under which it is called tolerable. Responses above the higher threshold count as frustrating. The score combines these groups into a single number between zero and one. The thresholds are configurable, and you should set them to match what your business considers fast and acceptable, not leave the defaults without thinking.

flowchart TD
    A["Raw results file"] --> B["Clean: remove ramp phases and helper labels"]
    B --> C["Slice by time, label, thread and error type"]
    C --> D["Compare with a baseline run"]
    D --> E["Find the weak step and the load level where it breaks"]
    E --> F["Report with evidence and a clear recommendation"]
        
FIG 8 — From a raw results file to a recommendation

Beware of missing samples

Thread-based tests send the next request only after the previous one has finished. When the server stalls for ten seconds, every thread waits, and the requests that real users would have sent during that stall never appear in the results. The results therefore under-represent slow periods, and the percentiles look better than what real visitors would feel. This effect, known as coordinated omission, is a limitation of closed-loop tests. Be aware of it when you interpret tail percentiles, and consider rate-driven test designs when your real traffic arrives independently of server speed.

Example: finding a hidden scheduled job

A team sliced their results into thirty-second buckets and saw a sharp spike in the ninety-ninth percentile every ten minutes. Matching the timestamps with server logs showed a scheduled cleanup job that locked a table. The standard report, which showed one overall percentile, had never revealed the pattern.

25Failures, Retries and Automated Pass or Fail Gates

What a thread does after a failed sample, and how teams turn results into decisions.

What happens after a failed sample

When a Sampler Result is marked as failed, the thread group decides what the thread does next. The thread can carry on with the next step, start its next loop, stop itself, stop the whole test after finishing running requests, or stop the whole test immediately. This choice shapes the load and the shape of your results. If failing threads stop themselves, then during a failure storm the number of active threads falls, the pressure on the application drops, and the system may look as if it recovered when in fact your own load faded away. For capacity tests, most teams choose to continue or to start the next loop, so the load stays steady and the failures stay visible.

!
Hidden Trap

A test that stops threads on error can produce a lovely recovery curve that never happened. Always compare the active threads graph with the plan. If the active count fell during the test, ask whether that fall came from errors, and whether the results after that moment still describe the load you intended.

Designing realistic retries

Real users and real clients often retry a failed action. A mobile app may retry a failed call automatically, and a person may press the button again. You can copy this behaviour with a loop controller that repeats a step while the previous sample failed. JMeter keeps a thread variable that records whether the last sample succeeded, and a controller can read it to decide whether to retry. The important rule is to keep each attempt as its own Sampler Result with a clear label, so that your report shows both the failures and the retries, rather than hiding failures behind eventual success.

Design choiceEffect on resultsWhen to use it
No retry, continue to the next stepEach failure appears once and the load stays steadyCapacity and stress tests
Retry with a clear labelFailures and retries both visible, load rises slightly under failureWhen real clients retry automatically
Stop the thread on errorLoad shrinks as errors growShort functional checks, rarely for load
Stop the whole test on errorTest ends at the first problemSmoke tests that guard a pipeline
Simple Analogy

Imagine a call centre test where each tester hangs up and goes home after the first busy signal. The phone lines look calmer and calmer, but only because the testers left. Retrying like real customers keeps the pressure on, and the busy signals remain in the record for everyone to see.

Using Sampler Results in automated gates

Many teams run short performance tests inside an automated delivery pipeline and use the results to decide whether a build may move forward. The test writes a results file, a small step reads it, calculates figures such as the ninety-fifth percentile per label and the error percent, and compares them with agreed limits. If a limit is broken, the pipeline stops. This turns performance from a once-a-quarter event into a daily guard.

1

Agree on measurable limits

Write down limits per business step, such as a maximum ninety-fifth percentile and a maximum error percent. Vague goals cannot be automated.

2

Run a short, stable test

Use a small, repeatable load with a fixed ramp-up and a stable environment, so differences between runs reflect code changes rather than noise.

3

Read the lean results file

Calculate the statistics per label from the saved samples, excluding ramp phases and helper steps.

4

Compare with limits and with the previous build

Fail the stage if a limit is crossed, and flag a large change compared with the last accepted build, even if the limit is still met.

5

Keep the evidence

Store the results file and the report with the build, so that a failed gate can be investigated later with the same data.

i
Practical Tip

Gates based on a single run can be flaky. Use a tolerance, repeat a failing test once before blocking a build, and track trends over several builds. A gate that blocks builds for random noise quickly loses the trust of the team.

Example: a quiet regression caught by a gate

A team added a nightly test with limits per label. One morning the gate failed on the search step: the ninety-fifth percentile had doubled, while the average had barely moved. The previous day’s change to a query had added a slow path for a small share of searches. Because the gate looked at the percentile and kept the evidence, the cause was found within an hour of the change.

26Troubleshooting: Symptoms, Causes and Fixes

Start from what you see in the results, and work toward the cause.

SymptomLikely causeFirst check
Everything is green but users complainNo content assertions, only status codes checkedOpen samples, read the body, add assertions
Extractor finds nothingWrong scope, wrong field to check or the value is in a sub-resultScope setting and the field to check
Variable name appears in the requestPrevious extractor failed to capture the valuePrevious sample’s response and the extractor pattern
Strange characters in text checksWrong encodingEncoding and the response header for character set
High elapsed time, low latencyLarge response or slow networkResponse size, compression and bandwidth
High connect timeSlow connection set-up or no connection reuseNetwork path and keep-alive settings
Report has thousands of rowsDynamic values in labels or many embedded resourcesLabel design and resource retrieval settings
Response data missing in the fileThe save setting for response data was offResult save configuration
Totals look larger than expectedParents and children counted togetherTransaction controller settings and report filters
Test tool crashes with out-of-memoryHeavy listeners or saved bodiesListener list and saved fields
Failures all from a few threadsBad or locked test dataGroup failed samples by thread name

A calm way to investigate

1

Reproduce with one thread

If the problem appears with a single thread, it is a script or application issue. If it only appears under load, think about capacity and the generator.

2

Open the failing sample

Read the code, the timings, the request and the response in that order.

3

Look at the previous sample

Many failures start one step earlier, where a value was not captured or a session was lost.

4

Group and count

Group failures by label, response code, thread name and time to see whether they are random, clustered or linked to a certain load level.

5

Change one thing at a time

Fix one suspected cause, rerun, and compare, rather than changing many settings together.

27Frequently Asked Questions

Quick answers to questions that come up in almost every project.

Q1What is the difference between a sampler and a Sampler Result?

The sampler is the element that performs the action. The Sampler Result is the record of one run of that action, with the timings, status, sizes and data. One sampler can produce thousands of results during a test.

Q2What is the difference between elapsed time and latency?

Elapsed time runs from the start of the request to the last byte of the response. Latency runs from the start of the request to the first byte. The difference between them is roughly the time spent downloading the response.

Q3Why is a sample marked failed when the status code is 200?

Because an assertion judged the content or the time to be wrong. The failure message in the result explains which assertion failed and why. A normal status code only means the server answered, not that the answer was correct.

Q4Are timer pauses included in the response time?

No. Timers run before the sampler starts measuring, so their delay is not part of the elapsed time of the sample. Idle time records such pauses separately, and a transaction controller can include them in a group total if you ask it to.

Q5Why do I not see response bodies in my results file?

By default, JMeter does not save response data, headers or request data in the results file, to protect file size and memory. You can switch on saving for these fields, but do it only for debugging or for failed samples.

Q6What does a response code that starts with “Non HTTP response code” mean?

It means the request failed before a normal server answer was received, for example because of a refused connection, an unknown host, a timeout or a handshake failure. The text after it names the technical problem.

Q7Which format is better for results, CSV or XML?

CSV is better for almost all load tests because it is compact, fast and works directly with the report generator. XML is useful for short debugging runs when you need full detail and nested sub-results.

Q8Why is my extractor not finding a value that I can see in the response?

Common reasons are that the extractor reads the wrong field, such as the body instead of the headers, that its scope excludes the sub-sample where the value appears, that the pattern does not match, or that the encoding is wrong. Check these in turn.

Q9How can I find which user caused a failure?

Use the thread name saved in each result. Group failed samples by thread name to see whether failures are spread across all users or concentrated in a few, which often points to bad test data.

Q10Can heavy result handling slow down my test?

Yes. Memory-hungry listeners, saved bodies and heavy assertions can starve the load generator and delay requests inside JMeter, so the measured times include delays that the application did not cause.

Q11Should sub-results be counted in the report?

Usually the report should count the parent result, because counting both the parent and its children double-counts the same work. Know how your report treats sub-results before you compare tests.

Q12Is it safe to share a results file?

Only if it is lean and has been checked. Files that contain request or response data may hold passwords, tokens and personal details. Clean or mask them first, and store files in protected locations.

28Summary and Key Takeaways

The Sampler Result is the foundation of every JMeter report. It is the record created each time a sampler runs, and it carries the identity, the timings, the status, the sizes, the thread information, the request, the response and the verdicts of the assertions. Extractors and assertions read it during the test, listeners display and save it, and reports turn thousands of them into statistics. If the records are rich, correct and lean, then your report is trustworthy and your debugging is fast. If they are thin, misleading or heavy, the report can be wrong while looking perfectly professional.

Key Takeaways

  • One run, one record — every sampler run creates one Sampler Result, and all reports are built from these records.
  • Read all the clocks — elapsed time, latency, connect time and idle time together show where time was spent.
  • Status code is not success — use content assertions so that the success flag reflects real business success.
  • Know the order of events — timers run before sampling, assertions after extractors, and listeners last, which explains many surprises.
  • Mind sub-results and scope — redirects, embedded resources and transactions nest results, and extractors only read the scope you choose.
  • Save lean and safe — choose fields before the run, prefer CSV, keep bodies for failures only, and protect result files.
  • Report with percentiles and stable labels — filter to the steady period, use numbered stable labels, and never trust the average alone.