Transaction Controller in JMeter
A load test sends hundreds of tiny requests, but people think in bigger steps like "log in," "search," and "pay." The Transaction Controller is the element that turns many small requests into one meaningful business step you can measure, report, and promise something about.
Imagine you order a pizza by phone. You tell the shop your address, choose a size, pick toppings, and give a payment method. That is four small actions, but you would never describe your evening as “I made four actions.” You would say, “I ordered a pizza, and it took twenty minutes.” The whole sequence is one experience, and the total time is the number that matters.
Websites work the same way. When a customer checks out in an online shop, the browser may send a dozen separate requests: view the basket, enter an address, choose delivery, pay, confirm. A load-testing tool sees a dozen lines in its report. A manager wants one line that says, “Checkout takes 2.4 seconds.” In Apache JMeter, the element that creates that single line is the Transaction Controller.
This guide starts from the very first idea and builds up to the habits of experienced performance engineers. You will learn what a transaction is, how the controller measures it, the two modes it can work in, what its two checkboxes really do, how it affects your reports, and the mistakes that quietly make test results wrong.
1What Is a Transaction Controller?
A Transaction Controller wraps several requests together and measures them as one named business step.
The Simple Definition
In JMeter, a sampler is one action that sends a request to the system under test and measures the answer. A logic controller is an element that decides the order or grouping of those actions. The Transaction Controller is a logic controller that places several samplers inside it and then produces an extra measurement: the total time those samplers took together, labelled with the controller’s own name.
If you put “Open Login Page,” “Submit Credentials,” and “Load Home Page” inside a Transaction Controller named “Login,” JMeter can report one number called “Login” that covers the whole journey, instead of only three separate numbers.
Think of a relay race. Each runner runs one leg, and the stopwatch for each leg is a sampler. The Transaction Controller is the official clock that starts when the first runner begins and stops when the last runner crosses the line. The team’s result is that one total time, not the pile of individual leg times.
A Transaction Is Not a Database Transaction
The word “transaction” causes a lot of confusion. In databases, a transaction means a group of changes that must all succeed or all be undone. In JMeter, a transaction is only a measuring group. It does not undo anything. It does not lock anything. It simply times and reports a set of steps together.
The Transaction Controller does not change what your test sends to the server. It only changes how the results are measured and shown. Removing it would not remove a single request.
2Why the Transaction Controller Exists
To see why we need it, picture a report without it.
The Problem
A modern web page is not one request. Opening a single product page may trigger a request for the page itself, several data calls, images, style files, and script files. A shopping journey of five pages could produce sixty or more lines in a raw report. Nobody in a business meeting wants to read sixty lines. They want answers to questions such as “How long does login take?” and “Is checkout fast enough?”
There is a second problem. A step that feels like one thing to the user may be made of several calls that must all succeed. If one of the five calls inside “Pay” fails, the customer’s payment failed, no matter how healthy the other four calls were. A raw list of requests does not tell you that the business step failed.
What It Gives You
One Number Per Business Step
Login, search, and checkout each get a single response time that matches what a person feels.
Pass or Fail For the Whole Step
A transaction fails if any request inside it fails, which mirrors the customer’s real experience.
Readable Reports
Managers see ten clear lines instead of hundreds of technical ones.
Targets You Can Promise
Service goals such as “checkout under three seconds for 95 percent of users” can be tied to a named step.
Real-World Motivation
A bank wants to promise that “Transfer Money” completes in under two seconds. Behind that one phrase sit calls to check the balance, validate the account, check limits, post the transfer, and send a notification. Teams in that situation group those calls into one named transaction so that the promise and the measurement use the same words.
3Core Concepts You Need First
A few words appear again and again in JMeter. Learn them once and the rest becomes easy.
Test Plan and Thread Group
The Test Plan is the whole saved test. A Thread Group sits under it and creates the virtual users, called threads. Each thread follows the same list of steps, and a Transaction Controller lives inside that list.
Sampler and Sample
A sampler is the element that sends a request. A sample is one measured result from it. In a web test, one HTTP Request sampler running once makes one sample. The controller does not replace samplers. It groups them.
Response Time
Response time is how long a request takes, from the moment it is sent until the full answer has arrived. A transaction’s response time combines the response times of the samplers inside it.
Think Time and Timers
Real people pause between actions. This think time is created in JMeter with elements called timers. Whether those pauses count inside a transaction’s time is one of the controller’s key choices, as we will see.
Listener and Report
A listener collects and displays results. Common ones are the Summary Report and the Aggregate Report, which show one row per label. A transaction’s label is the name you gave the controller.
| Term | Plain Meaning | Where You See It |
|---|---|---|
| Sampler | One request sent and measured | Under a Thread Group or controller |
| Sample | One measured result | A row in a listener |
| Logic controller | Decides order and grouping of steps | Under a Thread Group |
| Transaction Controller | Times several samplers as one named step | Wraps the samplers |
| Label | The name shown in reports | First column of a report |
| Timer | Adds think time | Under a controller or sampler |
| Listener | Shows or stores results | Under a Thread Group or Test Plan |
4Architecture and Where the Controller Sits
A JMeter test is a tree. The Transaction Controller is a branch that holds the requests belonging to one business step.
The Test Plan is the root. A Thread Group sits below it. Under the Thread Group you place one Transaction Controller for each business step, and inside each controller you place the samplers that make up that step. Timers, assertions, and other helpers can sit inside or outside, and where you put them changes what is measured.
flowchart TD
TP["Test Plan"] --> TG["Thread Group: Shoppers"]
TG --> T1["Transaction Controller: 01 Login"]
TG --> T2["Transaction Controller: 02 Search"]
TG --> T3["Transaction Controller: 03 Checkout"]
T1 --> S1["Sampler: Open Login Page"]
T1 --> S2["Sampler: Submit Credentials"]
T1 --> S3["Sampler: Load Home Page"]
T2 --> S4["Sampler: Search Request"]
T2 --> S5["Sampler: Load Results"]
T3 --> S6["Sampler: Add Address"]
T3 --> S7["Sampler: Pay"]
T3 --> S8["Sampler: Confirm Order"]
TG --> TM["Timer: Think Time between steps"]
TG --> LS["Listener: Aggregate Report"]
Reading the Diagram
The shopper Thread Group contains three business steps: Login, Search, and Checkout. Each is a Transaction Controller. Login contains three samplers, Search contains two, and Checkout contains three. In the final report you will see three transaction lines, along with the individual lines if you leave them visible. The timer sits under the Thread Group, outside the controllers, so the pauses between business steps are not counted as part of any step.
Only samplers placed inside the Transaction Controller are timed by it. A sampler beside it, or above it, is not part of that transaction, even if it runs just before or after.
Analogy: Chapters in a Book
A book is made of paragraphs, but readers talk about chapters. The Thread Group is the whole book, each Transaction Controller is a chapter, and each sampler is a paragraph. A table of contents that lists chapters is easy to read, while a list of every paragraph is not. The Transaction Controller gives your test report a table of contents.
5The Controller’s Settings Explained
The panel is small, but each field changes your numbers in an important way.
Name
The name is the label that appears in reports, so it is the most important field of all. A clear, consistent name makes reports readable and makes filtering easy. Use names such as “01_Login” and “02_Search,” not “Transaction Controller” and “Transaction Controller 2.”
Generate Parent Sample
This checkbox decides how the transaction appears in results.
- Unchecked (the traditional mode). JMeter records each inner sampler as its own normal sample, and then adds one extra sample at the end that represents the transaction. Your report contains both the small lines and the transaction line.
- Checked. JMeter records a single parent sample for the whole transaction, and the inner samplers become sub-results nested inside it. Summary reports then show only the transaction line, while detailed viewers can still open it to see the inner requests.
Include Duration of Timer and Pre-Post Processors in Generated Sample
This checkbox decides what the transaction’s time includes.
- Unchecked. The transaction time is based on the samplers themselves. Think-time pauses and the work of pre-processors and post-processors are not added.
- Checked. The pauses and processor work that happen inside the controller are added to the transaction’s time, which makes it longer and closer to the wall-clock time a person would spend.
If you check the “include duration of timer” option and your think-time timers are inside the controller, your transaction time will include the artificial pauses. A “one-second” login can suddenly look like a “nine-second” login. Decide on purpose whether you want that.
| Setting | Unchecked | Checked |
|---|---|---|
| Generate parent sample | Inner samples and one extra transaction sample both appear | Only the parent appears in summaries, inner samples become sub-results |
| Include duration of timer and pre-post processors | Pauses and processor time are left out | Pauses and processor time are added |
6Two Modes: Extra Sample or Parent Sample
The Generate Parent Sample checkbox changes how your reports look and how your totals are counted. Understanding it prevents the most common reporting error.
Mode One: The Extra Sample
In the default mode, each inner request is reported as normal. After the last request in the group finishes, JMeter adds one more sample whose label is the controller’s name and whose time is the total of the group. Because the transaction line is added on top of the normal lines, the total count of samples in your report is higher than the number of real requests sent.
For example, a transaction of three requests, run once, produces four lines: three real ones and one transaction line. If a report adds all lines together, it counts four “requests,” although only three were sent to the server.
Mode Two: The Parent Sample
With Generate Parent Sample checked, JMeter wraps the group in a single parent. A summary report shows just one line for the group. The three real requests are still stored, nested inside the parent, and can be opened in a detailed viewer. The total count then equals the number of transactions, not the number of individual requests.
flowchart TD
Q{"Generate Parent Sample checked?"} -- "No" --> A["Each inner request is its own sample"]
A --> A2["One extra sample added with the controller name"]
A2 --> A3["Report shows inner lines plus transaction line"]
Q -- "Yes" --> B["Inner requests become sub-results"]
B --> B2["One parent sample is created"]
B2 --> B3["Report shows only the transaction line"]
Parent Sample Checked
- One clean line per business step
- Totals count transactions, not extra lines
- Great for managers and dashboards
- Inner details still available when needed
Parent Sample Unchecked
- Inner requests visible in summaries for deep analysis
- Totals are inflated by the extra transaction lines
- Throughput numbers can be misleading
- Needs filtering to produce a clean report
In the extra-sample mode, a shop prints every item on the receipt and then adds a line that says “Total.” Counting lines gives you more lines than items. In the parent-sample mode, the receipt shows only the final basket total, and the individual items are in a folded detail section that you can open if you want.
7How a Transaction’s Time Is Calculated
The number on the transaction line is not magic. It follows a simple rule that you can check by hand.
The Basic Rule
The transaction’s response time is the combined time of the samplers inside it. If a login transaction contains three requests that take 0.4, 0.7, and 0.5 seconds, the transaction time is about 1.6 seconds. The result is not an average. It is a total, because a person doing the step really waits for all three.
What Is Left Out By Default
By default, the time spent in think-time pauses and in processors, such as scripts that prepare or analyse data, is not added. This is helpful, because you usually want the transaction line to say how fast the server was, not how long your artificial pauses lasted.
What Changes When You Include Timers
When you tick “include duration of timer and pre-post processors,” the pauses and processor time inside the controller are added. If the same login contains a three-second think time between steps, the transaction time becomes about 4.6 seconds instead of 1.6. This is not wrong, but it answers a different question: “How long does a user spend on login, including reading and typing?” instead of “How fast is the login service?”
sequenceDiagram
participant T as Virtual User Thread
participant C as Transaction Controller
participant S as Server Under Test
T->>C: Enter Login transaction
C->>S: Request 1 Open Login Page
S-->>C: Response 0.4 seconds
C->>S: Request 2 Submit Credentials
S-->>C: Response 0.7 seconds
C->>S: Request 3 Load Home Page
S-->>C: Response 0.5 seconds
C->>T: Report Login transaction of about 1.6 seconds
| Case | Request Times | Think Time Inside | Include Timers? | Transaction Time |
|---|---|---|---|---|
| A | 0.4 + 0.7 + 0.5 s | None | No | About 1.6 s |
| B | 0.4 + 0.7 + 0.5 s | 3 s | No | About 1.6 s |
| C | 0.4 + 0.7 + 0.5 s | 3 s | Yes | About 4.6 s |
| D | 0.4 + 0.7 + 0.5 s | Two pauses of 3 s | Yes | About 7.6 s |
The Safe Habit
Place think-time timers outside the controllers, between business steps, and leave the include option unchecked. Then the transaction line measures system speed, and the pauses stay visible only in the overall rhythm of the test.
Write down in your test notes which choice you made about timer duration. A reader seeing “Checkout: 6 seconds” has no way to know whether it included think time unless you tell them.
8Success and Failure of a Transaction
A transaction is only as strong as its weakest request.
The All-Or-Nothing Rule
A transaction is marked successful only when every sampler inside it succeeded. If even one inner request failed, the whole transaction is marked as failed. This matches real life. If the “Pay” request of a checkout fails, the customer did not complete their purchase, no matter how fast the other pages loaded.
The Response Message
The transaction sample carries a short message that says how many samples it contained and how many of them failed. When you open a failed transaction in a detailed viewer, that message tells you quickly whether one inner request or many were at fault. This is a handy first clue when investigating errors.
What This Does To Your Error Percentage
Consider a transaction of four requests, and suppose each request fails one percent of the time, independently. The chance that at least one of the four fails is about four percent. So a service whose individual requests look very healthy can still show a visibly higher failure rate at the business level. This is not a bug in the report. It is the truth about what the customer experiences, and it is a strong reason to measure transactions.
Failure And What Happens Next
A failed transaction does not stop the test by itself. What happens after a failure depends on the Thread Group’s error action and on the structure of your test. With the default “continue” action, the thread moves on to the next step, even after a failed transaction. That is realistic for many tests, but if a failed login makes later steps meaningless, you may prefer to start the next loop.
A transaction can be marked failed for reasons that have nothing to do with the server, such as a bad test account or an expired token. Always look inside failed transactions before blaming the system.
9How the Controller Works Inside
A short look at the engine room explains most of the behaviour you will see.
Each Thread Has Its Own Copy
When a test starts, JMeter gives every virtual user its own private copy of the test elements. That includes each Transaction Controller. So the stopwatch belongs to the thread. Thread number five’s login timer has nothing to do with thread number six’s. This is why transactions from many users can run at the same time without disturbing each other.
The Stopwatch Idea
Conceptually, the controller starts a clock when the first inner element begins, lets the inner elements run in their normal order, and stops the clock when the last one has finished. Then it builds the result sample. In the extra-sample mode, it adds that sample after the inner ones. In the parent-sample mode, it assembles the parent and attaches the inner samples to it.
What Happens If The Group Is Skipped Or Cut Short
If a condition prevents the inner elements from running, for example an If Controller that is false, the transaction may produce no sample at all. If a thread is stopped in the middle, the unfinished transaction may never be reported. When you see fewer transaction lines than iterations, check for conditions and stop actions before suspecting a bug.
Results Flow To Listeners
The generated sample travels to the listeners just like any other sample. This is why every standard listener can show transactions with no extra setup. A listener sees only a label, a time, a status, and the other usual fields.
Because the generated sample looks like any other sample, JMeter reports treat the transaction exactly like a request. That is why filters and dashboards work on transaction names with no special tools.
10Data Flow: From Request to Dashboard
Follow one transaction from the first request to the final chart and the whole picture falls into place.
flowchart TD
A["Thread enters the Transaction Controller"] --> B["Inner samplers send requests"]
B --> C["Server returns responses"]
C --> D["Assertions check the responses"]
D --> E{"Parent sample mode?"}
E -- "Yes" --> F["Parent sample created with sub-results"]
E -- "No" --> G["Inner samples reported then one extra sample added"]
F --> H["Listeners receive the transaction sample"]
G --> H
H --> I["Results file written to disk"]
I --> J["Report or dashboard groups rows by label"]
J --> K["Percentiles, errors, and throughput per transaction"]
Enter
The thread reaches the controller and the timing begins.
Work
Inner samplers fire in order, and the server answers each one.
Judge
Assertions decide whether each response was correct, and any failure marks the transaction as failed.
Package
The controller builds the transaction sample, either as an extra line or as a parent.
Record
Listeners show it and a results file stores it.
Report
Tools group the rows by label and compute averages, percentiles, error rates, and throughput for each transaction.
11Choosing Transaction Boundaries
Deciding what goes inside a transaction is a design skill. The tool is simple, but the choice is not.
Start From the User’s Point of View
A good transaction matches a step that a real person would name. “Log in,” “Search for a product,” “Add to basket,” and “Pay” are good. “Call number three and number four” is not. Ask yourself, “If I described this step to a customer, what would I call it?” That name is your transaction name.
Keep It the Right Size
- Too small and you recreate the raw report. A transaction with one request adds no value, except as a clearer name.
- Too large and you hide where the slowness is. A single “Whole Journey” transaction cannot tell you whether login or checkout was slow.
- Just right usually means one user-visible step, covering the few requests needed to complete it.
Match the Business and the Promise
Transactions should line up with the targets the business cares about. If the business promise is “search results in under two seconds,” then “Search” must be a single transaction that measures exactly that, from the search request to the arrival of the results.
Include Everything the User Waits For
A page the user sees may load extra files after the main page, such as images and scripts. If the user would wait for them, make sure your transaction includes them. If your test skips them, say so, because the real experience is slower than the measured one.
| Design | Good or Bad | Reason |
|---|---|---|
| 01_Login with three requests | Good | Matches one visible step |
| Every single request as its own transaction | Weak | Recreates the noisy raw report |
| One transaction for the whole visit | Weak | Hides which step is slow |
| 03_Checkout including payment confirmation | Good | Matches the user’s goal |
| Transaction that includes long think time | Risky | Measures people, not the system |
12Naming Conventions That Save Hours
Names look trivial, but in a team and across months, they decide whether reports are usable.
Why Names Matter So Much
The transaction name becomes the label in every listener, results file, and dashboard. Tools group, sort, and filter by that label. A messy name makes every later step harder. Also, when reports from different weeks are compared, a name that changed slightly breaks the comparison.
A Simple Convention
- Add a number prefix such as 01, 02, and 03, so that reports sort in the order of the user’s journey.
- Add a short business name after it, such as Login, Search, or Checkout.
- Use a common marker for transactions, such as the letters TX at the start, so that a filter can show only transactions and hide inner requests.
- Avoid spaces and odd characters if your tools struggle with them. An underscore is a safe separator.
- Never put secrets or personal data in names. Names end up in files and dashboards that many people see.
| Weak Name | Strong Name | Why It Is Better |
|---|---|---|
| Transaction Controller | TX01_Login | Says what it is, and sorts first |
| Step 2 | TX02_Search_Product | Describes the business step |
| pay | TX05_Pay_By_Card | Consistent style and clear meaning |
| Checkout for user john | TX06_Checkout | No personal data, stable across runs |
Name the inner samplers consistently too, with a prefix that shows which transaction they belong to, such as “Login – Submit Credentials.” Then even in the raw report, you can tell at a glance which step owns each request.
13Nesting Transaction Controllers
One transaction can sit inside another. This is powerful and easy to overdo.
What Nesting Looks Like
You can place a Transaction Controller inside another. For example, an outer transaction named “TX_Purchase_Journey” can contain inner transactions named “TX_Add_To_Basket,” “TX_Enter_Address,” and “TX_Pay.” The outer one gives a number for the whole purchase, and the inner ones show where the time went.
How Time And Counts Behave
Each controller measures the samplers beneath it. The outer transaction includes everything inside the inner ones. So the outer time is at least as large as the sum of the inner times. In the extra-sample mode, nesting adds extra lines at each level, which makes the report even more crowded and the total counts even more inflated.
When Nesting Is Wise
- When the business has both a headline number, such as “Purchase journey,” and sub-steps whose times need separate tracking.
- When different teams own different sub-steps and each wants its own measurement.
When Nesting Is Unwise
- When you are only nesting to make the tree look tidy.
- When the report becomes so crowded that nobody reads it.
- When think-time timers sit between the inner steps and the include-timer option is on, since the outer transaction will then contain a lot of artificial waiting.
Do not add the times of an outer and an inner transaction together. The outer one already contains the inner ones, so adding them counts the same time twice.
14Transaction Controllers With Loops and Counts
Loops multiply everything, including the number of transaction samples. Plan the arithmetic before you press start.
One Transaction Sample Per Pass
Each time a thread passes through a Transaction Controller, it creates one transaction sample. If a user’s journey passes through Login once and Search three times per iteration, and the Thread Group repeats ten times, then each user creates ten Login transactions and thirty Search transactions.
The Counting Formula
The number of transaction samples for a given controller equals the number of threads, multiplied by the Thread Group Loop Count, multiplied by the number of passes through that controller in one iteration.
A Worked Example
You have 100 threads and a Loop Count of 5. Each iteration passes once through Login, twice through Search, and once through Checkout. You expect 500 Login transactions, 1,000 Search transactions, and 500 Checkout transactions. If the report shows very different numbers, something stopped early, a condition skipped a step, or loops were nested in a way you did not intend.
| Transaction | Passes Per Iteration | Threads | Loop Count | Expected Transactions |
|---|---|---|---|---|
| TX01_Login | 1 | 100 | 5 | 500 |
| TX02_Search | 2 | 100 | 5 | 1,000 |
| TX03_Checkout | 1 | 100 | 5 | 500 |
Login Only Once
If a real user logs in once and then repeats other steps, put the login transaction inside a Once Only Controller. Otherwise every iteration logs in again and your Login transaction count, and the load on the login service, will be far higher than in real life.
After each run, compare the number of samples in each transaction line with your calculated number. A match means you understand your test. A mismatch is a clue worth following before you trust any other figure.
15Timers and Think Time Around Transactions
Where you place a pause decides whether your transaction measures the system or the pretend person.
How Timers Find Their Samplers
A timer applies to every sampler in its scope. A timer placed directly under the Thread Group applies to every sampler beneath that group, including the ones inside controllers. A timer placed inside a Transaction Controller applies to the samplers inside it. A timer runs just before its sampler, so the pause comes before the request, not after it.
Three Placement Choices
Timer Outside Every Transaction
Put the pause between business steps, not inside them. The transaction lines then measure server speed cleanly.
Timer Inside, Include Unchecked
The pauses still happen but are not added to the transaction time. Works, but is easy to misunderstand later.
Timer Inside, Include Checked
The pauses are added to the transaction time. Use only when you really want to measure the user’s total time.
A Pause Sampler Between Transactions
A dedicated pause element placed between controllers makes the think time obvious in the tree.
The Hidden Trap of a Group-Level Timer
If you place one timer directly under the Thread Group, it also applies to every request inside every transaction. You may end up with a pause before every single request, not only between steps. The load becomes lighter than you intended, and if the include-timer option is checked, your transaction times become inflated.
Imagine timing a barista making a coffee. If you start the stopwatch when the customer begins choosing and stop it when the cup arrives, you measure the customer’s indecision too. If you time only from the moment the order is placed, you measure the barista. Timer placement is the choice of where to start the stopwatch.
16Assertions and Processors Inside Transactions
Checks and helpers work with transactions, and a few behaviours deserve attention.
Assertions: Making Failure Honest
An assertion checks that a response is correct, for example that a page contains a certain word. Because a transaction fails when any inner request fails, assertions make the transaction result meaningful. Without assertions, a fast error page would count as a success, and your transaction would look perfect while customers saw errors.
Where to Put Them
An assertion placed under a sampler checks only that sampler. An assertion placed under the Transaction Controller applies to the samplers in its scope. For beginners, the simplest, most predictable design is to place the assertion directly under the sampler it checks, then confirm the behaviour with a debugging listener.
Pre-Processors and Post-Processors
A post-processor, such as one that extracts a session token from a response, often sits inside a transaction, because the value is needed by the next step in the same transaction. Their work normally does not count in the transaction time unless you check the include-timer option. Very slow scripts can then hide inside the transaction and quietly inflate it.
Sampler Sends the Request
The inner request goes to the server and the answer returns.
Post-Processor Extracts Data
A token or an identifier is taken from the response for later use.
Assertion Judges the Answer
The response is checked, and a failure marks the sample and the transaction as failed.
Controller Packages the Result
When all inner steps are done, the transaction result is built and sent to the listeners.
A missing token that was supposed to be extracted does not always fail loudly. The next request may simply send an empty value and get an error. Always add an assertion that confirms a token or identifier was really found.
17Conditions, Retries, and Error Handling
Real journeys branch and recover. Transactions need to cope with that.
Conditions Inside a Transaction
An If Controller can sit inside a Transaction Controller, so that some inner requests run only when a condition is true. The transaction then measures whatever actually ran. This makes transaction times vary between iterations, because different paths take different time. When the path varies a lot, consider splitting it into separate named transactions, so each one measures a single kind of path.
Conditions Around a Transaction
An If Controller can also sit outside, deciding whether the whole transaction runs. When the condition is false, no transaction sample is created for that pass. Remember this when you compare counts, because transaction numbers will be lower than the number of iterations.
Retries and Polling
A While Controller inside a transaction repeats requests until something becomes true, such as an order reaching the status “complete.” Each repeated request adds to the transaction time. That is correct, because a real user would wait for those retries. Always limit the number of repeats and add a small pause, so that a condition that never becomes true cannot trap a thread forever.
The Thread Group’s Error Action
- Continue keeps going after a failure. The failed transaction is recorded, and the next step runs as normal.
- Start Next Thread Loop abandons the rest of the iteration. Later transactions in that pass are never created, so their counts will be lower.
- Stop Thread and Stop Test end the user or the test, and the unfinished transactions disappear from the report.
When a failed login makes later steps pointless, choose the error action that starts the next loop. That way you do not fill your report with a long chain of meaningless failures that all trace back to one cause.
18Transactions Across Several Thread Groups
Real traffic is a mixture of user types, and each type has its own business steps.
One Group Per Kind of User
An online store has browsers, buyers, and administrators. Each Thread Group can hold its own set of transactions. Browsers might have “Home,” “Category,” and “Product.” Buyers might have “Login,” “Basket,” and “Checkout.” Administrators might have “Login” and “Daily_Report.”
Sharing a Name Across Groups
Reports group rows by label. If the browser group and the buyer group both have a transaction called “Login,” their results are combined into one line. This may be what you want, or it may hide a difference. If the two kinds of users use different login paths, give them different names, such as “TX01_Login_Buyer” and “TX01_Login_Admin.”
Reuse Without Copy and Paste
When the same business step appears in several groups, copying it everywhere invites mistakes, because a fix in one place is forgotten in the others. JMeter offers ways to reuse a block of steps, such as a Test Fragment that is called by a Module Controller or an Include Controller. A Transaction Controller can wrap such a call, so you keep one definition of the step and still measure it under the right name in each group.
| Thread Group | Transactions | Why They Are Separate |
|---|---|---|
| Browsers | TX_Home, TX_Category, TX_Product | Many users, light work |
| Buyers | TX_Login, TX_Basket, TX_Checkout | Fewer users, heavy work |
| Admins | TX_Login_Admin, TX_Daily_Report | Rare users, expensive reports |
19Transaction Controller Versus Similar Controllers
Several controllers group things, and beginners often pick the wrong one. Here is how they differ.
| Controller | What It Does | Creates a Timing Sample? | Typical Use |
|---|---|---|---|
| Transaction Controller | Groups samplers and measures them together | Yes | Business-step timing and reporting |
| Simple Controller | Groups elements for tidiness only | No | Organising the tree and scoping timers or settings |
| Loop Controller | Repeats its children | No | Doing a step several times |
| Once Only Controller | Runs its children on the first iteration only | No | Login and one-time setup |
| If Controller | Runs its children if a condition is true | No | Optional or branching steps |
| Module Controller | Calls a reusable block elsewhere in the plan | No | Reusing a step in many places |
| Include Controller | Loads steps from another test file | No | Sharing steps between test files |
| Throughput Controller | Runs children for a share or number of passes | No | Mixing behaviours by percentage |
Combining Them
These controllers are not rivals. They work together. A common pattern puts a Transaction Controller inside a Loop Controller, so that a “view product” step is timed on every repeat. Another puts a Transaction Controller inside an If Controller, so the step is measured only when it runs.
If you want a number for a business step, use a Transaction Controller. If you only want to organise or scope things, use a Simple Controller. If you want to repeat, branch, or run once, use the controller made for that job.
20Reading Transactions in Reports
The controller is only useful if you read its numbers correctly.
The Reports You Will Meet
- The Summary Report and Aggregate Report show one row per label, with counts, averages, percentiles, error rates, and throughput.
- The View Results Tree shows each sample in detail, and with a parent sample you can open a transaction and see its inner requests.
- The HTML dashboard report, generated after a run from a results file, shows tables and charts per label.
The Double-Counting Trap
In the extra-sample mode, the transaction line is added on top of the normal lines. The total row at the bottom of a report adds every line, so it counts the real requests and the transaction lines. Total samples and total throughput look bigger than the load you really sent. Percentiles for the total row mix individual requests and whole transactions, which have very different durations, so that row is hard to interpret.
How To Avoid It
- Use the parent sample mode so only transactions appear in summaries
- Or filter the report by a naming marker, such as keeping only labels that start with TX
- Or keep two views: one with transactions only, one with inner requests only
- Never quote the total row without saying what it contains
What Goes Wrong
- Throughput looks higher than the real request rate
- Error percentage can be diluted or doubled
- Averages for the total row are misleading
- Comparisons with other tools or earlier runs fail
Transactions Per Second Is Not Database TPS
The throughput of a transaction line tells you how many business steps per second, such as logins per second. That is useful, but it is not the same as the database transactions per second that a database administrator would talk about. Always say which one you mean.
21Live Dashboards and Filtering by Transaction
Teams often stream results to a dashboard during a run. Transactions make those dashboards readable.
The Backend Listener
The Backend Listener sends results to an external system, such as a time-series database, while the test runs. A dashboard tool such as Grafana can then show live charts. By default, such charts may include every label, which is a lot. The listener can be told to send only labels that match a pattern, so your dashboard shows only the transactions.
Using the Naming Marker
This is where a good naming convention pays off. If every transaction starts with the same marker, one simple pattern selects them all, and the dashboard shows a short, clean list. Without a marker, you must list every name by hand and update that list whenever someone adds a step.
What To Chart
Response Time Per Transaction
Lines for each business step over time, so slow steps stand out at once.
Percentiles
The 90th, 95th, and 99th percentile for the key transactions, because averages hide pain.
Transactions Per Second
The rate of completed business steps, which should match your planned load.
Error Rate Per Transaction
Shows which business step is failing, not just that something is failing.
Place a marker on the dashboard for the start and end of each test phase. When a transaction time jumps, you can immediately see whether it happened during ramp-up, steady state, or ramp-down.
22Service Goals and Pass-Fail Rules Per Transaction
Transactions let you attach a promise to each business step and check it automatically.
From Business Promise to Test Rule
A service goal is a sentence such as “95 percent of searches finish in under two seconds, with fewer than one percent errors.” The Transaction Controller gives you a named measurement that matches that sentence exactly. You compute the 95th percentile of the “TX02_Search” label and compare it with two seconds.
An Example Table of Goals
| Transaction | 95th Percentile Goal | Error Limit | Why This Goal |
|---|---|---|---|
| TX01_Login | Under 2 s | Under 1 percent | First impression, entry point for everything |
| TX02_Search | Under 2 s | Under 1 percent | Most frequent action |
| TX03_Add_To_Basket | Under 1.5 s | Under 0.5 percent | Small action, should feel instant |
| TX04_Checkout | Under 3 s | Under 0.5 percent | Money step, errors cost real sales |
Checking Goals Automatically
A small script can read the results file after a run, compute the percentile and the error rate for each transaction label, and compare them with the goals. If a limit is broken, the script returns a failing result, and a build pipeline stops. This turns performance from a once-a-year worry into an everyday check.
Be Careful With Averages
Goals based on averages hide the unhappy users. A transaction that takes one second for most people and thirty seconds for a few has a comfortable average and a terrible experience for those few. Use percentiles for goals, and look at the maximum to spot extreme cases.
If your transaction time includes think time, you cannot compare it with a goal that talks about server speed. Check your include-timer setting before judging any result against a service goal.
23Transactions in Distributed Testing
When several machines generate load, transaction results are gathered together by label.
How It Works
In distributed mode, a controller machine sends the Test Plan to several worker machines. Each worker runs the complete plan, including every Transaction Controller. Each worker produces its own transaction samples, and the results flow back to be merged. Because reports group by label, the same transaction from different workers appears as a single line.
Points to Remember
- Counts add up. With three workers, each running 100 threads, you will see transaction counts three times higher than with one worker.
- Names must match. All workers run the same file, so labels are identical. If you use variables in names, make sure they do not accidentally create a different label on each worker.
- Clocks should agree. Time-based charts merge samples by timestamp, so workers should have synchronised clocks.
- Check each worker’s health. A struggling worker adds its own delay to the transactions it measures, and that delay looks like server slowness.
Add the worker name as a separate field in your results, if your setup allows it. When one worker’s transactions look slower than the others, you immediately suspect that machine or its network path rather than the server.
24Performance and Scalability of the Test Machine
The controller is cheap, but its choices can change how much memory and disk your test uses.
Memory
In parent-sample mode, JMeter keeps the inner samples attached to the parent until the result has been handled. Heavy listeners that keep everything in memory, especially those that store sub-results with their full response bodies, can use much more memory than in the other mode. Over a long test with many users, this adds up and can cause out-of-memory errors on the test machine.
Disk
The results file grows with the number of samples. In the extra-sample mode, transaction lines add to the number of rows. In parent mode, sub-results may be stored inside each row or skipped, depending on your save settings. Choose what to save on purpose, and avoid saving full response bodies in a large run.
Processor
The controller itself uses very little processor time. The costly parts are the things inside it: parsing large responses, running scripts, and encrypting connections. When a test machine struggles, its own slowness can inflate transaction times and look like server slowness.
Practical Advice
- Run real tests from the command line, without the window.
- Disable heavy listeners during load, and write results to a file.
- Do not save response bodies unless you are debugging.
- Watch the processor and memory of the test machine while the test runs.
25Monitoring, Logging, and Metrics
A load test creates pressure. Monitoring tells you what the pressure did to each business step.
The Numbers Worth Watching Per Transaction
| Metric | What It Tells You | Why It Matters |
|---|---|---|
| Average response time | The mean time of the business step | Quick view, but can hide outliers |
| 90th, 95th, 99th percentile | The time under which most executions finish | Shows what the unlucky users feel |
| Minimum and maximum | The fastest and slowest executions | Spots extreme cases |
| Error percentage | Share of transactions that failed | Shows stability of the business step |
| Throughput | Completed transactions per second | Confirms the planned load was delivered |
| Count | How many times the step ran | Should match your calculated number |
Why Percentiles Beat Averages
Imagine ninety-nine checkouts that take one second and one that takes one hundred seconds. The average looks like two seconds, yet one customer waited more than a minute and a half. Percentiles reveal that pain, which is why experienced testers use them for goals and reports.
Look Inside When a Transaction Looks Bad
A slow transaction is a symptom. The cause is one or two slow inner requests. Keep the inner samples available, either through parent-sample details or through a second report that shows only inner requests, so that you can drill down quickly from “Checkout is slow” to “the payment call is slow.”
Server Side Numbers
JMeter measures what the client sees. To find the cause, also collect server numbers such as processor use, memory, disk, database connections, and queue lengths. Line them up on one timeline with your transaction charts. When a transaction time rises at the same moment a server resource saturates, you have found your bottleneck.
Logging Your Settings
Always record the number of threads, the ramp-up, the loop settings, and the two checkbox choices of your controllers next to the results. Numbers without settings cannot be compared next month.
26Security and Safety
Grouping requests does not change what they do, but it does change what ends up in your reports and files.
Only Test What You Are Allowed To Test
Sending a flood of requests to a system you do not own, or have no written permission to test, may be illegal. Even inside your own company, tell the operations team before a big test. Cloud providers and hosting companies often have their own rules for load testing, so read them first.
Keep Sensitive Data Out of Names and Results
- Do not put usernames, email addresses, or account numbers into transaction names. Names appear in dashboards that many people can see.
- Be careful with saved response bodies. They can contain personal data, tokens, and session cookies.
- Do not upload results files with sensitive content to public places or share them in open chats.
Real Side Effects Multiply
A checkout transaction that runs thousands of times creates thousands of real orders and may trigger emails, payments, or stock changes. Use a test environment with test payment settings, point email at a mail sink, and plan clean-up in a tearDown Thread Group.
Accounts and Defences
Login transactions repeated many times with the same account can lock it or trigger security defences. Use many different test accounts, and be clear in your report about whether security defences were active during the test.
A transaction named after a real customer or a real secret code becomes part of every chart and file. Treat names as public, and keep them generic and stable.
27Advantages, Disadvantages, and Trade-Offs
Every tool has strengths and weaknesses. Knowing both helps you use it wisely.
Advantages
- Turns many small requests into one business measurement
- Matches how users and managers talk about the system
- Marks a step failed if any request inside it fails
- Makes reports shorter and more readable
- Allows service goals per business step
- Works with all listeners and dashboards without extra tools
- Can be nested to show both headline and detail numbers
Disadvantages
- Extra-sample mode inflates totals and throughput
- Includes or excludes think time depending on a checkbox that is easy to forget
- Can hide which inner request is slow if used without detail
- Parent mode can use more memory with heavy listeners
- Nested transactions make reports crowded and confusing
- Name changes break comparison between runs
Key Trade-Offs
| Choice | One Side | Other Side |
|---|---|---|
| Parent sample or extra sample | Clean report, details nested | Inner details visible in summaries, but inflated totals |
| Include timers or not | Total user time | Pure system speed |
| Small or large transactions | Precise diagnosis | Simple, readable report |
| Nested or flat | Headline plus detail | One clear level |
| Many names or few names | Fine-grained goals | Easier dashboards |
28Design Patterns and Anti-Patterns
Experienced testers keep returning to a few shapes that work and a few traps that fail.
Patterns That Work
One Transaction Per User-Visible Step
Login, search, basket, and pay each get a transaction that a customer would recognise.
Timers Between, Not Inside
Think time sits between transactions so transaction lines measure system speed.
Marker Prefix For Filtering
A common start to every transaction name lets dashboards and scripts select them in one rule.
Headline Plus Detail
A nested outer transaction for the whole journey, with inner transactions for the key steps.
Reusable Steps
A shared fragment wrapped in a Transaction Controller, so one definition is measured the same way everywhere.
Goal Table
A written table of percentile and error goals for each transaction, checked after every run.
Traps to Avoid
What It Looks Like
Every request is wrapped in its own Transaction Controller, and the extra-sample mode is left on.
Why It Hurts
The report doubles in length, every request appears twice, totals are inflated, and nothing is easier to read than before.
Better Approach
Group by user-visible step, and use the parent sample mode for clean summaries.
What It Looks Like
A think-time timer is placed under the Thread Group, and the include-timer option is checked on every controller.
Why It Hurts
Pauses are added to every transaction. A login that takes one second is reported as eight, and the team starts tuning a server that was never slow.
Better Approach
Keep think time between transactions, and leave the include-timer option unchecked unless you truly want total user time.
What It Looks Like
The whole user visit is wrapped in a single transaction named “Journey,” and it is the only transaction in the report.
Why It Hurts
You see that the journey is slow but never learn which step is responsible, and you cannot attach goals to individual steps.
Better Approach
Keep the headline transaction if you wish, but nest named inner transactions for the main steps.
29Best Practices and Common Mistakes
Habits that save time and protect the trustworthiness of your results.
Best Practices
Name Steps Like a Customer Would
Use clear, numbered, consistent names that survive from one run to the next.
Choose the Mode on Purpose
Pick parent sample or extra sample deliberately, and write down which one you used.
Keep Think Time Outside
Place pauses between transactions, so lines measure system speed.
Add Assertions
A fast error page is not a success. Confirm the content is correct so failures are honest.
Count Before You Run
Calculate the expected number of each transaction and compare it with the report.
Report Percentiles and Errors
Averages hide pain, so lead with percentiles and error rates per transaction.
Keep Detail Available
Make sure you can drill from a slow transaction to the inner request that caused it.
Common Mistakes at a Glance
| Mistake | Result | Fix |
|---|---|---|
| Extra-sample mode with a total row quoted | Inflated requests and throughput | Use parent mode or filter by label |
| Think time inside with timers included | Transaction times look far too slow | Move timers outside, or uncheck the option |
| Group-level timer applied to every request | Pauses before every request, lighter load | Place timers where you mean them |
| Different names for the same step across runs | Broken comparisons | Use a fixed naming convention |
| No assertions | Errors counted as successes | Add content checks |
| Same name in two thread groups | Results merged by accident | Add a suffix per user type |
| Adding outer and inner transaction times | Double counting | Treat the outer time as the whole |
30Real-World Examples
These scenarios show how transactions are used in practice. They describe how teams at well-known kinds of companies commonly think, and they are illustrations, not claims about any company’s private tools.
A Retail Giant Measuring Checkout
A very large online retailer rehearses a sale day. The test groups the checkout requests into one transaction called “Checkout,” and the business promise is that most customers finish in under three seconds. The team watches the 95th percentile of that single line during the sale simulation, and drills into the inner payment call whenever the line rises.
A Streaming Service Measuring Sign-In and Home Screen
A streaming service expects many people to open the app right after a big release. The test wraps sign-in and the home screen load into a transaction called “Sign_In_And_Home.” That is the exact path every viewer takes, so one number says whether the entry experience is healthy, no matter how many calls hide behind it.
A Bank Measuring a Money Transfer
A bank wants to be sure that “Transfer Money” completes quickly and reliably. The test groups the balance check, account validation, limit check, posting, and notification into one transaction. Because a transaction fails if any inner call fails, the failure rate of that line is the true rate at which customers cannot complete a transfer.
A Ride-Hailing App Measuring Booking
A ride-hailing company measures “Request_Ride” as one transaction that includes locating the user, estimating the fare, and creating the booking. Product managers care about this number because it is exactly what a rider waits for on a rainy evening.
A Small Team Cleaning Up a Noisy Report
A small team has a test report of two hundred lines that nobody reads. They wrap the requests into six business transactions, turn on the parent sample mode, and use a naming prefix to filter the dashboard. The next meeting takes ten minutes instead of an hour, because everyone looks at the same six lines.
31Adding a Transaction Controller Step by Step
Reading is useful, but building makes it stick. Follow these steps in order.
Start With Plain Samplers
Build a Thread Group with one thread and three HTTP Request samplers: open page, submit form, load result. Add a debugging listener and run once to prove the script works.
Add the Controller
Right-click the Thread Group, choose Add, then Logic Controller, then Transaction Controller. Give it a clear name such as “TX01_Login.”
Move the Samplers Inside
Drag the three samplers under the controller. The tree now shows them indented below it.
Run and Read the Extra Line
With both checkboxes unchecked, run again. You should see three normal lines and one extra line named “TX01_Login.” Check that its time is about the sum of the three.
Try the Parent Sample Mode
Tick “Generate parent sample” and run again. In a summary report you now see one line. In the results tree, open the transaction to find the three requests nested inside.
Experiment With Think Time
Add a small constant pause inside the controller. Run with and without the include-timer option, and watch the transaction time change. This single experiment teaches the most important lesson about the controller.
Force a Failure
Point one request at a wrong address. The inner request fails, and the whole transaction should be marked as failed. Read the response message of the transaction to see the counts.
Scale Up Carefully
Add more threads and loops, calculate expected transaction counts, move to non-GUI mode, and write results to a file for the report.
32A Complete Example: Designing Transactions for an Online Store
Let us design the transactions for a realistic store, step by step, the way an experienced engineer would.
Step 1: List What a Customer Does
A typical shopper opens the home page, logs in, searches for a product, opens a product page, adds it to the basket, enters an address, pays, and sees a confirmation. That is eight business steps. Behind them sit about thirty requests, once images and scripts are counted.
Step 2: Decide the Transactions
| Transaction Name | Requests Inside | Goal for the 95th Percentile |
|---|---|---|
| TX01_Home | Home page and its resources | Under 2 s |
| TX02_Login | Login page, credentials, redirect | Under 2 s |
| TX03_Search | Search request and results page | Under 2 s |
| TX04_Product | Product details and related items | Under 2 s |
| TX05_Add_To_Basket | Add request and basket refresh | Under 1.5 s |
| TX06_Address | Address form and validation | Under 1.5 s |
| TX07_Pay | Payment request and confirmation call | Under 3 s |
| TX08_Confirmation | Order summary page | Under 2 s |
Step 3: Decide the Think Time
Between each pair of transactions, a random pause of three to eight seconds imitates reading and typing. The timers are placed between the controllers, so no pause ever sits inside a transaction. The include-timer option stays unchecked.
Step 4: Choose the Mode
The team chooses the parent sample mode, so that the report shows exactly eight transaction lines. When a line looks slow, they open it in a detailed viewer to see the inner requests.
Step 5: Calculate the Counts
With 100 threads and a Loop Count of 10, and each transaction passing once per iteration, they expect 1,000 samples for each of the eight lines, 8,000 in total. If the report shows 7,200 total, they know exactly where to look: probably a failed login that caused the next loop to start early.
Step 6: Check Against Goals
After the run, a script reads the results file and compares each line with the goals in the table. All lines pass except TX07_Pay, whose 95th percentile is 3.8 seconds against a goal of 3 seconds. The team opens the Pay transaction in a detailed viewer, sees that the call to the payment provider is the slow inner request, and now has a precise problem to hand to the right engineers.
When asked how you would design transactions, describe this flow: list the user’s steps, name the transactions after them, keep think time outside, choose the parent sample mode, calculate expected counts, write goals per transaction, and drill into inner requests when a goal fails.
33Troubleshooting Transaction Problems
When transactions misbehave, the cause is almost always one of a small set of familiar suspects.
| Symptom | Likely Cause | What To Do |
|---|---|---|
| Report shows twice as many lines as expected | Extra-sample mode shows inner and transaction lines | Use parent mode or filter by label |
| Total throughput higher than the real load | Transaction lines counted along with real requests | Compute throughput from inner requests only |
| Transaction time much bigger than the sum of requests | Timers or processors included | Uncheck the include option or move timers out |
| Transaction time smaller than expected | Pauses and processor time excluded, or some requests skipped | Check the option and any conditions inside |
| Transaction fails but all lines look green | A hidden inner failure, or an assertion on the controller | Open the transaction and read its message |
| Fewer transactions than iterations | A false condition, or an error action that skipped steps | Check If Controllers and error settings |
| No transaction line at all | Samplers not actually inside the controller | Check indentation in the tree |
| Two user types merged into one line | Same transaction name in two thread groups | Use different names |
| Dashboard shows too many labels | No filter or naming marker | Filter by prefix |
| Memory problems in long tests | Heavy listeners holding sub-results | Use file output and light listeners |
A Simple Debugging Routine
Shrink the problem. Use one thread, one loop, and a debugging listener. Open the transaction line and its inner requests. Count the samples, read the time of each request, and add them up. Compare the total with the transaction time. If the numbers match, the structure is right and you can scale up. If they do not, the difference is the clue.
When a restaurant bill looks wrong, you do not argue about the final total. You look at each line item and add them up. Debugging a transaction is the same: check the parts, add them, and compare with the total.
34Settings and Ideas Beginners Often Confuse
Many wrong results come from mixing up two things that sound alike. Here are the most common pairs.
Transaction and Sample
A sample is one measured request. A transaction is a group of samples measured together under one name. One transaction usually contains several samples, so a report that says “ten thousand samples” and one that says “ten thousand transactions” describe very different amounts of traffic.
Transaction Controller and Simple Controller
Both are containers, but only the Transaction Controller produces a timing line. The Simple Controller is for tidiness and scope. If you expected a number and got none, you may have used the wrong container.
Parent Sample and Extra Sample
Parent mode nests the inner requests inside one line. Extra mode keeps the inner requests as normal lines and adds one more. The first keeps counts clean. The second keeps details visible in summaries but inflates totals.
Include Timers and Generate Parent
These two checkboxes are independent. One decides how results are packaged. The other decides what time is counted. Checking one does not change the other, and many confusing reports come from checking the wrong one while thinking about the other.
Think Time and Response Time
Think time is an artificial pause that imitates a person. Response time is how long the system took. A transaction can include one, the other, or both, depending on your settings. Always know which your number means.
Business Transaction and Database Transaction
A JMeter transaction is a measuring group. A database transaction is a group of changes that succeed or fail together. They share a word and nothing else.
| Pair | First Meaning | Second Meaning |
|---|---|---|
| Transaction and sample | A group measured together | One measured request |
| Transaction and Simple Controller | Creates a timing line | Only groups for tidiness |
| Parent and extra sample | One line with nested details | Details plus one added line |
| Include timers and parent sample | What time is counted | How results are packaged |
| Think time and response time | Artificial pause | Real system time |
| JMeter and database transaction | A measuring group | An all-or-nothing set of changes |
Say out loud, in one sentence each, what your transaction contains, what its time includes, how it appears in the report, and how many of it you expect. If you cannot, the test is not ready.
35A Case Study: The Fast Login That Was Not Fast
This story is a composite of problems that engineering teams commonly meet. It shows how small controller choices lead to big wrong conclusions.
The Situation
A team is preparing to release a new login service. The business promise is that login must complete in under two seconds for 95 percent of users. A junior engineer builds a test where login, token fetch, and profile load are placed inside a Transaction Controller named “Login.” To imitate real behaviour, a pause of four seconds is placed between each request inside the controller, and the “include duration of timer” box is checked.
What the Report Said
The report showed a login time of about thirteen seconds at the 95th percentile. The team panicked. The release was delayed. Two engineers spent three days tuning the login service, adding caches and rewriting a database query.
What Was Really Wrong
Think Time Was Counted
Two pauses of four seconds sat inside the controller, and the include-timer option was checked, so eight seconds of the thirteen came from artificial waiting and not from the server.
The Goal Compared Different Things
The business promise talked about the speed of the service. The measurement included the pretend person’s reading time. The comparison was meaningless.
The Settings Were Not Written Down
Nobody had recorded the checkbox choices, so nobody noticed that the transaction number included pauses until the third day.
How the Team Fixed the Test
They moved the pauses outside the controller, unchecked the include-timer option, switched on the parent sample mode, and added a naming prefix. The transaction line now showed about 1.5 seconds at the 95th percentile, comfortably under the goal. The tuning work had not been needed. Worse, it had delayed a release that was already healthy.
A transaction number is only as meaningful as its settings. Before judging any transaction against a goal, check what its time includes, and write that down next to the result.
36Automating Transaction Checks in Pipelines
Transactions make performance checks easy to automate, because each business step has a name, a time, and a status.
Why Automate
A system that was fast last month can become slow after a few small changes, and nobody notices because each change looks harmless. Running a short test after every important change, and checking each transaction against its goal, catches slow drift early, when the cause is still easy to find.
A Typical Flow
Deploy to a Test Environment
The pipeline builds the application and puts it in an environment that resembles production.
Run JMeter Without the Window
A short, light test runs from the command line and writes results to a file.
Read Each Transaction Line
A script selects labels that start with the naming marker and computes the percentile and error rate for each one.
Compare With the Goal Table
Each transaction is compared with its own limits, and a broken limit fails the build with a clear message naming the step.
Keep the Evidence
The results file and report are stored with the build so anyone can compare today with last week.
What Makes This Work
- Stable names. The script finds each transaction by name, so renaming a step breaks the check.
- A consistent marker. One prefix lets the script ignore inner requests and focus on business steps.
- The same settings every time. If the mode or the include-timer option changes, results cannot be compared.
- Sensible limits. Short pipeline tests are noisy, so allow some tolerance and use percentiles over larger samples where you can.
Short pipeline checks catch large regressions, not slow leaks. Keep a longer test before major releases, and do not treat a quick green result as proof of long-run health.
37Quick Reference: Choosing Your Settings at a Glance
When you are in a hurry, use this page to pick the right settings for the job in front of you.
| If You Want | Generate Parent Sample | Include Timers | Also Do |
|---|---|---|---|
| A clean management report | Checked | Unchecked | Use a naming prefix and goal table |
| To see inner requests in summaries | Unchecked | Unchecked | Filter the total row, and say what it contains |
| The user’s total time including reading | Checked | Checked | State clearly that think time is included |
| Pure server speed for a business step | Checked | Unchecked | Place timers between transactions |
| A headline plus step details | Checked on both levels | Unchecked | Nest inner transactions in one outer |
| Low memory use on long tests | Either | Unchecked | Use light listeners and file output |
Five Questions to Ask Before Every Run
What Is Inside?
Can you list the requests in each transaction in one sentence?
What Does the Time Include?
Are pauses and processor work counted or not, and is that what your goal assumes?
How Will It Appear?
Will the report show only transactions, or inner requests too, and how will totals be read?
How Many Do I Expect?
Have you calculated threads times loops times passes for each transaction?
Is It Safe?
Will thousands of repetitions harm anything real, such as customers, bills, or shared systems?
38Glossary of Terms
Keep this page handy. Every word here appears somewhere in the guide.
| Term | Plain Meaning |
|---|---|
| Aggregate Report | A listener that shows counts, averages, percentiles, and errors per label |
| Assertion | A check that decides whether a response was correct |
| Business transaction | A step a customer would name, such as login or checkout |
| Extra sample mode | Inner requests reported as normal, plus one added transaction line |
| Label | The name that identifies a row in a report |
| Listener | An element that shows or stores results |
| Logic controller | An element that decides order or grouping of steps |
| Nested transaction | A transaction placed inside another one |
| Parent sample | A single result that holds the inner requests as sub-results |
| Percentile | The time under which a given share of executions finished |
| Sample | One measured result of a sampler |
| Sampler | An element that sends a request and measures the answer |
| Simple Controller | A container used for tidiness and scope |
| Sub-result | An inner request nested under a parent sample |
| Think time | The pause a real person takes between actions |
| Thread | One virtual user in JMeter |
| Throughput | How many items are handled per unit of time |
| Timer | An element that adds a pause before a sampler |
| Transaction Controller | A controller that measures several samplers as one named step |
39Pages, Embedded Resources, and Transactions
A web page is more than its main request. How you treat the extra files decides whether your transaction matches what a visitor feels.
What Embedded Resources Are
When a browser opens a page, the first answer is only a plan. It lists images, style files, script files, and fonts that the browser must fetch before the page looks complete. These extra files are called embedded resources. A load test that ignores them measures only the first answer and misses much of the real waiting time.
How JMeter Handles Them
The HTTP Request sampler has an option to retrieve all embedded resources. When it is on, JMeter fetches those extra files after the main page, and it can fetch several at the same time like a real browser. The page’s sample then covers the main request, and the extra files appear as nested sub-results under it. A Transaction Controller can wrap such a page request together with the next steps, so that one transaction covers a whole screen of the user’s journey.
Choosing Between Three Designs
| Design | What Is Measured | Good For | Weakness |
|---|---|---|---|
| Main page only | The first answer from the server | Testing back-end services | Understates what the visitor waits for |
| Page with embedded resources | Main page plus the extra files | Matching real page-load time | Heavier on the test machine and the network |
| Transaction around several pages | The whole step, such as login and landing page | Business reporting | Less precise about which page is slow |
Caching and Realism
A real browser remembers files it has already downloaded. If your test downloads every image again for every user and every loop, it sends far more traffic than real returning visitors would. JMeter offers a Cache Manager that imitates a browser’s memory. Whether you use it depends on what you want to model: first-time visitors, who download everything, or returning visitors, who reuse a lot.
Content Delivery Networks
Many sites serve images and scripts from a separate network of servers close to users, called a content delivery network. If your test downloads those files too, you load that network as well, which may be unwanted, and which your agreement with the provider may not allow. Decide on purpose whether to include those hosts, and use filters to leave them out if needed.
Say in your report whether embedded resources were included. A transaction time that includes them is not comparable with one that does not, and a reader who does not know the difference may draw the wrong conclusion.
40Transactions for APIs and Microservices
Not every test starts from a web page. Many modern tests send calls straight to services, and transactions still help.
An API Workflow Is Also a Business Step
A mobile app might create an order by calling several services in a row: check stock, reserve items, calculate price, take payment, and confirm. The user sees one button press. The test sees five calls. Wrapping the five calls in a transaction named “Place_Order” gives a single number that matches the button press, and a single failure status that matches whether the order was really placed.
Chained Calls and Extracted Values
API workflows often pass values from one call to the next, such as an order number returned by the first call and needed by the third. Post-processors extract these values, and later calls use them. When the extraction fails, the following calls fail too, and the transaction is marked as failed. This makes the transaction a useful early warning that something in the chain broke, even before you read individual errors.
Looking for the Slow Service
A slow “Place_Order” transaction does not say which service is slow. The inner calls do. Keep their names clear, such as “Place_Order – Reserve Items” and “Place_Order – Take Payment,” so that a quick look at the inner lines points to the service to investigate. Combine this with tracing or monitoring on the server side to see what happens inside each service.
Fan-Out and Parallel Calls
Some workflows call several services at the same time. A Transaction Controller measures the elapsed time of the group, so if two calls run in parallel, the transaction time reflects the longer one, not the sum. If your test makes calls one after another when the real application makes them at the same time, your transaction will look slower than reality. Check how the real client behaves before you design the test.
Mirror the Real Client
Send calls in the same order, with the same parallelism, as the real application does.
Name By Business Action
“Place_Order” is understood by everyone. “Calls 4 to 8” is understood by nobody.
Assert Each Call
Check the status and key fields of every response, so failures inside the chain are honest.
Watch Rate Limits
Services often limit calls per user or per key. A busy test may trip these limits and show errors that are not real faults.
41Frequently Asked Questions
Quick answers to the questions beginners ask most.
42Summary and Key Takeaways
The whole guide in a few lines.
Remember These Points
- A Transaction Controller groups samplers and measures them as one named business step. It does not change what is sent to the server.
- A transaction is successful only if every request inside it succeeds, which mirrors what a customer experiences.
- Generate Parent Sample gives one clean line per step with details nested. Leaving it off adds an extra line and inflates totals and throughput.
- Include duration of timer and pre-post processors decides whether think time is counted. Keep pauses between transactions so the number measures the system.
- Use clear, numbered, prefixed names so reports, filters, dashboards, and scripts can find your transactions and compare runs.
- Calculate threads x loops x passes for each transaction before you run, and compare it with the report afterwards.
- Set percentile and error goals per transaction, watch the load generator, keep names free of sensitive data, and test only systems you are allowed to test.