Transaction Controller in JMeter

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.

Everyday Analogy

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.

i
Remember

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

Benefit

One Number Per Business Step

Login, search, and checkout each get a single response time that matches what a person feels.

Benefit

Pass or Fail For the Whole Step

A transaction fails if any request inside it fails, which mirrors the customer’s real experience.

Benefit

Readable Reports

Managers see ten clear lines instead of hundreds of technical ones.

Benefit

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.

TermPlain MeaningWhere You See It
SamplerOne request sent and measuredUnder a Thread Group or controller
SampleOne measured resultA row in a listener
Logic controllerDecides order and grouping of stepsUnder a Thread Group
Transaction ControllerTimes several samplers as one named stepWraps the samplers
LabelThe name shown in reportsFirst column of a report
TimerAdds think timeUnder a controller or sampler
ListenerShows or stores resultsUnder 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"]
    
Figure 1: Three Transaction Controllers grouping eight samplers under one Thread Group

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.

!
Scope Rule

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

Everyday Analogy

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.
!
Watch Out

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.

SettingUncheckedChecked
Generate parent sampleInner samples and one extra transaction sample both appearOnly the parent appears in summaries, inner samples become sub-results
Include duration of timer and pre-post processorsPauses and processor time are left outPauses 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"]
    
Figure 2: What the report shows in each of the two modes

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
Everyday Analogy

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
    
Figure 3: The controller adds up the time of the requests inside it
CaseRequest TimesThink Time InsideInclude Timers?Transaction Time
A0.4 + 0.7 + 0.5 sNoneNoAbout 1.6 s
B0.4 + 0.7 + 0.5 s3 sNoAbout 1.6 s
C0.4 + 0.7 + 0.5 s3 sYesAbout 4.6 s
D0.4 + 0.7 + 0.5 sTwo pauses of 3 sYesAbout 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.

i
Pro Tip

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.

1%
failure rate of each request
4
requests in the transaction
~4%
chance the whole transaction fails

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.

!
Watch Out

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.

i
Good to Know

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"]
    
Figure 4: How a transaction travels from the first request to the report
1

Enter

The thread reaches the controller and the timing begins.

2

Work

Inner samplers fire in order, and the server answers each one.

3

Judge

Assertions decide whether each response was correct, and any failure marks the transaction as failed.

4

Package

The controller builds the transaction sample, either as an extra line or as a parent.

5

Record

Listeners show it and a results file stores it.

6

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.

DesignGood or BadReason
01_Login with three requestsGoodMatches one visible step
Every single request as its own transactionWeakRecreates the noisy raw report
One transaction for the whole visitWeakHides which step is slow
03_Checkout including payment confirmationGoodMatches the user’s goal
Transaction that includes long think timeRiskyMeasures 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 NameStrong NameWhy It Is Better
Transaction ControllerTX01_LoginSays what it is, and sorts first
Step 2TX02_Search_ProductDescribes the business step
payTX05_Pay_By_CardConsistent style and clear meaning
Checkout for user johnTX06_CheckoutNo personal data, stable across runs
i
Pro Tip

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.
!
Watch Out

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.

Transactions = threads x loop count x passes per 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.

TransactionPasses Per IterationThreadsLoop CountExpected Transactions
TX01_Login11005500
TX02_Search210051,000
TX03_Checkout11005500

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.

i
Pro Tip

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

Option 1

Timer Outside Every Transaction

Put the pause between business steps, not inside them. The transaction lines then measure server speed cleanly.

Option 2

Timer Inside, Include Unchecked

The pauses still happen but are not added to the transaction time. Works, but is easy to misunderstand later.

Option 3

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.

Option 4

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.

Everyday Analogy

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.

1

Sampler Sends the Request

The inner request goes to the server and the answer returns.

2

Post-Processor Extracts Data

A token or an identifier is taken from the response for later use.

3

Assertion Judges the Answer

The response is checked, and a failure marks the sample and the transaction as failed.

4

Controller Packages the Result

When all inner steps are done, the transaction result is built and sent to the listeners.

!
Watch Out

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.
i
Pro Tip

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 GroupTransactionsWhy They Are Separate
BrowsersTX_Home, TX_Category, TX_ProductMany users, light work
BuyersTX_Login, TX_Basket, TX_CheckoutFewer users, heavy work
AdminsTX_Login_Admin, TX_Daily_ReportRare users, expensive reports

19Transaction Controller Versus Similar Controllers

Several controllers group things, and beginners often pick the wrong one. Here is how they differ.

ControllerWhat It DoesCreates a Timing Sample?Typical Use
Transaction ControllerGroups samplers and measures them togetherYesBusiness-step timing and reporting
Simple ControllerGroups elements for tidiness onlyNoOrganising the tree and scoping timers or settings
Loop ControllerRepeats its childrenNoDoing a step several times
Once Only ControllerRuns its children on the first iteration onlyNoLogin and one-time setup
If ControllerRuns its children if a condition is trueNoOptional or branching steps
Module ControllerCalls a reusable block elsewhere in the planNoReusing a step in many places
Include ControllerLoads steps from another test fileNoSharing steps between test files
Throughput ControllerRuns children for a share or number of passesNoMixing 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.

i
Rule of Thumb

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

Chart

Response Time Per Transaction

Lines for each business step over time, so slow steps stand out at once.

Chart

Percentiles

The 90th, 95th, and 99th percentile for the key transactions, because averages hide pain.

Chart

Transactions Per Second

The rate of completed business steps, which should match your planned load.

Chart

Error Rate Per Transaction

Shows which business step is failing, not just that something is failing.

i
Pro Tip

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

Transaction95th Percentile GoalError LimitWhy This Goal
TX01_LoginUnder 2 sUnder 1 percentFirst impression, entry point for everything
TX02_SearchUnder 2 sUnder 1 percentMost frequent action
TX03_Add_To_BasketUnder 1.5 sUnder 0.5 percentSmall action, should feel instant
TX04_CheckoutUnder 3 sUnder 0.5 percentMoney 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.

!
Watch Out

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.
i
Pro Tip

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.

GUI
only for building and debugging
Non-GUI
for every real load run
File
write results to disk, view them later

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

MetricWhat It Tells YouWhy It Matters
Average response timeThe mean time of the business stepQuick view, but can hide outliers
90th, 95th, 99th percentileThe time under which most executions finishShows what the unlucky users feel
Minimum and maximumThe fastest and slowest executionsSpots extreme cases
Error percentageShare of transactions that failedShows stability of the business step
ThroughputCompleted transactions per secondConfirms the planned load was delivered
CountHow many times the step ranShould 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.

!
Watch Out

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

ChoiceOne SideOther Side
Parent sample or extra sampleClean report, details nestedInner details visible in summaries, but inflated totals
Include timers or notTotal user timePure system speed
Small or large transactionsPrecise diagnosisSimple, readable report
Nested or flatHeadline plus detailOne clear level
Many names or few namesFine-grained goalsEasier 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

Pattern

One Transaction Per User-Visible Step

Login, search, basket, and pay each get a transaction that a customer would recognise.

Pattern

Timers Between, Not Inside

Think time sits between transactions so transaction lines measure system speed.

Pattern

Marker Prefix For Filtering

A common start to every transaction name lets dashboards and scripts select them in one rule.

Pattern

Headline Plus Detail

A nested outer transaction for the whole journey, with inner transactions for the key steps.

Pattern

Reusable Steps

A shared fragment wrapped in a Transaction Controller, so one definition is measured the same way everywhere.

Pattern

Goal Table

A written table of percentile and error goals for each transaction, checked after every run.

Traps to Avoid

ANTI-PATTERN 01 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.

ANTI-PATTERN 02 Avoid
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.

ANTI-PATTERN 03 Avoid
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

1

Name Steps Like a Customer Would

Use clear, numbered, consistent names that survive from one run to the next.

2

Choose the Mode on Purpose

Pick parent sample or extra sample deliberately, and write down which one you used.

3

Keep Think Time Outside

Place pauses between transactions, so lines measure system speed.

4

Add Assertions

A fast error page is not a success. Confirm the content is correct so failures are honest.

5

Count Before You Run

Calculate the expected number of each transaction and compare it with the report.

6

Report Percentiles and Errors

Averages hide pain, so lead with percentiles and error rates per transaction.

7

Keep Detail Available

Make sure you can drill from a slow transaction to the inner request that caused it.

Common Mistakes at a Glance

MistakeResultFix
Extra-sample mode with a total row quotedInflated requests and throughputUse parent mode or filter by label
Think time inside with timers includedTransaction times look far too slowMove timers outside, or uncheck the option
Group-level timer applied to every requestPauses before every request, lighter loadPlace timers where you mean them
Different names for the same step across runsBroken comparisonsUse a fixed naming convention
No assertionsErrors counted as successesAdd content checks
Same name in two thread groupsResults merged by accidentAdd a suffix per user type
Adding outer and inner transaction timesDouble countingTreat 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.

1

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.

2

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.”

3

Move the Samplers Inside

Drag the three samplers under the controller. The tree now shows them indented below it.

4

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.

5

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.

6

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.

7

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.

8

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 NameRequests InsideGoal for the 95th Percentile
TX01_HomeHome page and its resourcesUnder 2 s
TX02_LoginLogin page, credentials, redirectUnder 2 s
TX03_SearchSearch request and results pageUnder 2 s
TX04_ProductProduct details and related itemsUnder 2 s
TX05_Add_To_BasketAdd request and basket refreshUnder 1.5 s
TX06_AddressAddress form and validationUnder 1.5 s
TX07_PayPayment request and confirmation callUnder 3 s
TX08_ConfirmationOrder summary pageUnder 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.

i
Interview Insight

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.

SymptomLikely CauseWhat To Do
Report shows twice as many lines as expectedExtra-sample mode shows inner and transaction linesUse parent mode or filter by label
Total throughput higher than the real loadTransaction lines counted along with real requestsCompute throughput from inner requests only
Transaction time much bigger than the sum of requestsTimers or processors includedUncheck the include option or move timers out
Transaction time smaller than expectedPauses and processor time excluded, or some requests skippedCheck the option and any conditions inside
Transaction fails but all lines look greenA hidden inner failure, or an assertion on the controllerOpen the transaction and read its message
Fewer transactions than iterationsA false condition, or an error action that skipped stepsCheck If Controllers and error settings
No transaction line at allSamplers not actually inside the controllerCheck indentation in the tree
Two user types merged into one lineSame transaction name in two thread groupsUse different names
Dashboard shows too many labelsNo filter or naming markerFilter by prefix
Memory problems in long testsHeavy listeners holding sub-resultsUse 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.

Everyday Analogy

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.

PairFirst MeaningSecond Meaning
Transaction and sampleA group measured togetherOne measured request
Transaction and Simple ControllerCreates a timing lineOnly groups for tidiness
Parent and extra sampleOne line with nested detailsDetails plus one added line
Include timers and parent sampleWhat time is countedHow results are packaged
Think time and response timeArtificial pauseReal system time
JMeter and database transactionA measuring groupAn all-or-nothing set of changes
i
Self-Check Before You Press Start

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

1

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.

2

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.

3

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.

i
The Lesson

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

1

Deploy to a Test Environment

The pipeline builds the application and puts it in an environment that resembles production.

2

Run JMeter Without the Window

A short, light test runs from the command line and writes results to a file.

3

Read Each Transaction Line

A script selects labels that start with the naming marker and computes the percentile and error rate for each one.

4

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.

5

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.
!
Watch Out

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 WantGenerate Parent SampleInclude TimersAlso Do
A clean management reportCheckedUncheckedUse a naming prefix and goal table
To see inner requests in summariesUncheckedUncheckedFilter the total row, and say what it contains
The user’s total time including readingCheckedCheckedState clearly that think time is included
Pure server speed for a business stepCheckedUncheckedPlace timers between transactions
A headline plus step detailsChecked on both levelsUncheckedNest inner transactions in one outer
Low memory use on long testsEitherUncheckedUse light listeners and file output

Five Questions to Ask Before Every Run

Question 1

What Is Inside?

Can you list the requests in each transaction in one sentence?

Question 2

What Does the Time Include?

Are pauses and processor work counted or not, and is that what your goal assumes?

Question 3

How Will It Appear?

Will the report show only transactions, or inner requests too, and how will totals be read?

Question 4

How Many Do I Expect?

Have you calculated threads times loops times passes for each transaction?

Question 5

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.

TermPlain Meaning
Aggregate ReportA listener that shows counts, averages, percentiles, and errors per label
AssertionA check that decides whether a response was correct
Business transactionA step a customer would name, such as login or checkout
Extra sample modeInner requests reported as normal, plus one added transaction line
LabelThe name that identifies a row in a report
ListenerAn element that shows or stores results
Logic controllerAn element that decides order or grouping of steps
Nested transactionA transaction placed inside another one
Parent sampleA single result that holds the inner requests as sub-results
PercentileThe time under which a given share of executions finished
SampleOne measured result of a sampler
SamplerAn element that sends a request and measures the answer
Simple ControllerA container used for tidiness and scope
Sub-resultAn inner request nested under a parent sample
Think timeThe pause a real person takes between actions
ThreadOne virtual user in JMeter
ThroughputHow many items are handled per unit of time
TimerAn element that adds a pause before a sampler
Transaction ControllerA 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

DesignWhat Is MeasuredGood ForWeakness
Main page onlyThe first answer from the serverTesting back-end servicesUnderstates what the visitor waits for
Page with embedded resourcesMain page plus the extra filesMatching real page-load timeHeavier on the test machine and the network
Transaction around several pagesThe whole step, such as login and landing pageBusiness reportingLess 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.

!
Watch Out

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.

Tip

Mirror the Real Client

Send calls in the same order, with the same parallelism, as the real application does.

Tip

Name By Business Action

“Place_Order” is understood by everyone. “Calls 4 to 8” is understood by nobody.

Tip

Assert Each Call

Check the status and key fields of every response, so failures inside the chain are honest.

Tip

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.

Q1What does a Transaction Controller do?
It groups several samplers and produces a measurement for the whole group under its own name, so you can report a business step such as login or checkout as one line.
Q2Does it change the requests that are sent?
No. It only changes how results are measured and shown. Removing the controller would not remove any request.
Q3Is it the same as a database transaction?
No. A database transaction makes a set of changes succeed or fail together. A JMeter transaction is only a measuring group and does not undo or lock anything.
Q4What does Generate Parent Sample do?
It makes JMeter record one parent result per transaction with the inner requests nested inside, so summary reports show one line per business step and totals count transactions rather than extra lines.
Q5Why does my report show each request twice?
In the extra-sample mode, inner requests appear as normal lines and a transaction line is added on top. Use the parent sample mode, or filter the report by label, to avoid the clutter and the inflated totals.
Q6What does “include duration of timer and pre-post processors” mean?
When checked, the pauses and processor work inside the controller are added to the transaction time. When unchecked, the time is based on the requests themselves.
Q7Where should I put think-time timers?
Usually between transactions, outside the controllers. That keeps transaction lines focused on system speed and keeps the pauses from inflating them.
Q8When is a transaction marked as failed?
When any request inside it fails. This matches what a real customer experiences, because one failed call can break the whole step.
Q9Can I put one Transaction Controller inside another?
Yes. The outer one measures the whole and the inner ones show the parts. Do not add the outer and inner times together, because the outer already contains the inner ones.
Q10How do I choose what goes in a transaction?
Group the requests that make up one step a user would name. Avoid making each request its own transaction, and avoid wrapping the whole visit in one.
Q11Why are my transaction counts different from the number of iterations?
Conditions may skip the step, an error action may start the next loop early, the step may run more than once per iteration, or threads may have stopped. Calculate the expected count and look for the difference.
Q12How do I show only transactions on a dashboard?
Give every transaction a common name prefix, and tell the report or the Backend Listener to select labels that match that prefix.
Q13Does the controller work in distributed tests?
Yes. Each worker runs the full plan and produces its own transaction samples, and reports merge them by label. Counts add up across workers.
Q14Should I use averages or percentiles for transaction goals?
Use percentiles, usually the 90th, 95th, or 99th. Averages hide the slow executions that unhappy users experience.
Q15Does the controller slow down my test machine?
The controller itself costs very little. The things inside it, such as large responses, scripts, and heavy listeners that keep sub-results, are what use memory and processor time.
Q16How is it different from a Simple Controller?
A Simple Controller only groups elements for tidiness and scope. A Transaction Controller also generates a timing result for the group.

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.