The JMeter Pre-Processor Explained

The JMeter Pre-Processor Explained

A beginner-friendly but production-minded guide to the elements that get every request ready just before it leaves, so that your virtual users behave like real people instead of identical robots.

Picture a chef in a busy restaurant kitchen. Before the first order arrives, the chef chops onions, measures spices, and lines up pans. Cooks call this preparation mise en place, which is French for “everything in its place”. When an order comes in, the chef does not stop to find a knife. Everything is ready, so the dish leaves the kitchen quickly and correctly.

A load test has the same need. When JMeter is about to send a request, it often needs something prepared first: a different user name for each virtual user, a fresh session token, a value fetched from a database, a timestamp, or a small change to the address being called. If every virtual user sent exactly the same fixed request, the test would look nothing like real traffic, and many systems would reject or cache the repeated requests. The elements that do this last-minute preparation are called Pre-Processors.

This guide teaches Pre-Processors from zero. You will learn what they are, where they run, how far their reach extends, and the main members of the family. Then we go deeper into how they work internally, how variables travel, how to choose between similar elements, and what separates a beginner script from a production-quality test: performance, scalability, monitoring, security, design patterns, anti-patterns, and troubleshooting. Every new term is explained the first time it appears, and every big idea comes with an everyday comparison.

WWhat Is a Pre-Processor?

A Pre-Processor is a small helper that runs just before a request is sent.

Apache JMeter is a free, open-source tool from the Apache Software Foundation. It pretends to be many users at the same time and measures how a system behaves under that crowd. A JMeter test is described by a test plan, which is a tree of small building blocks called elements. Some elements send requests, and these are called samplers. A Pre-Processor is an element that does some work immediately before a sampler runs.

The simple definition

A Pre-Processor prepares the ground for a sampler. It can set or change variables, modify the request that is about to be sent, fetch data from somewhere, or apply a limit. Whatever it does, it does it after the plan has decided that a sampler will run, and before the sampler actually sends anything.

Everyday analogy

Think of an actor in a theatre. Before walking on stage, the actor visits the dressing room for costume and makeup. The audience never sees that room, but it changes how the actor appears. A Pre-Processor is the dressing room of a request.

What it is not

A Pre-Processor is not a sampler, so it does not send requests of its own and it does not appear as a row in the results. It is also not a Post-Processor, which does its work after the response comes back. And it is not a Config Element, which supplies defaults and data sources. The next chapters show how these neighbours differ, because confusing them is the most common beginner problem.

1
moment it runs: just before the sampler
0
results rows of its own
Many
kinds in the Pre-Processors menu
i
Good to know

A variable in JMeter is a named value that belongs to one virtual user. You write it as a name inside a dollar sign and curly brackets, and JMeter replaces it with the current value when a request is sent. Most Pre-Processors work by setting variables.

WWhy We Need to Prepare Before a Request

Real users are all different, and a test full of identical users proves very little.

Imagine a thousand customers visiting an online shop. Each one signs in with their own account, receives their own session, adds different items, and sends different addresses. If a test sends the same account name a thousand times, strange things happen. The shop may lock the account, return cached answers, or follow a shortcut that real traffic never takes. The result looks like a test, not like life.

Four reasons to prepare a request

Reason 1

Unique identity

Each virtual user needs their own name, password, or account number, so the system sees many people instead of one.

Reason 2

Fresh values

Many requests carry values that must be new each time, such as a time stamp, a random number, or an order reference.

Reason 3

Values from earlier steps

An earlier reply may hold a token or session identifier that the next request must send back.

Reason 4

Limits and guards

Sometimes the preparation is a safety net, such as a maximum waiting time for a request that might hang.

What goes wrong without preparation

Without preparation the test may report excellent speed for the wrong reasons. Cached answers come back in a blink. Repeated sign-ins hit a shortcut. A request with an expired token returns a fast error. In each case the numbers look good while the test has quietly stopped measuring what users really do.

Test with preparation

  • Each virtual user behaves like a different person
  • Caches and shortcuts are used as in real life
  • Tokens and identifiers stay valid
  • Results reflect real server work

Test without preparation

  • All users look identical to the server
  • Caches make responses unrealistically fast
  • Expired or reused values cause hidden errors
  • Results flatter the system
i
Production note

Teams that run large tests often find that the first draft of a script is far too uniform. Adding preparation steps is usually the biggest single step towards a realistic test.

WWhere Pre-Processors Fit in the Order of Execution

JMeter runs element types in a fixed order, and Pre-Processors come early.

When a sampler is about to run, JMeter does not simply go from top to bottom through the tree. It follows a fixed order by element type. According to the JMeter documentation, the order for each sampler is: Configuration Elements first, then Pre-Processors, then Timers, then the Sampler itself, then Post-Processors, then Assertions, and finally Listeners.

flowchart LR
    A["Config Elements"] --> B["Pre-Processors"]
    B --> C["Timers"]
    C --> D["Sampler sends the request"]
    D --> E["Post-Processors"]
    E --> F["Assertions"]
    F --> G["Listeners"]
FIG 1 · The order JMeter follows for every sampler.
Everyday analogy

Think of mailing a parcel. First you gather the materials, then you wrap the parcel, then you wait in the queue at the post office, then you hand it over. After that comes the receipt check and the record keeping. The wrapping must happen before the handing over, whatever order you happened to pick up the tape and paper in.

Two important consequences

  • Position in the tree does not change the type order. A Pre-Processor written below a sampler in the tree still runs before that sampler, as long as it is in scope.
  • Nothing runs without a sampler. Pre-Processors, Timers, Post-Processors and Assertions are only processed when there is a sampler they apply to. An element with no sampler in its scope does nothing.
StepElement typePlain meaning
1Config ElementsSet defaults and supply data
2Pre-ProcessorsPrepare this particular request
3TimersPause before sending
4SamplerSend the request and wait for the answer
5Post-ProcessorsStudy the answer and capture values
6AssertionsCheck that the answer is correct
7ListenersDisplay or save the result
!
Watch out

Because Config Elements run before Pre-Processors, a Pre-Processor cannot change what a Config Element has already done for this sampler. If you need a value in place before a Config Element, set it earlier, for example in a previous step or in a setup stage.

SScope: Which Samplers Get Prepared

Position in the tree decides how many requests a Pre-Processor serves.

A test plan is a tree. At the top is the Test Plan, under it are thread groups, which are the crowds of virtual users, and below those sit controllers and samplers. You add a Pre-Processor by right-clicking an element and choosing Add, then Pre Processors. The element you right-click becomes its parent, and the parent decides its scope, the set of samplers it prepares.

flowchart TD
    TP["Test Plan"] --> TG["Thread Group"]
    TG --> P0["Pre-Processor at group level: runs before every sampler in the group"]
    TG --> S1["Sampler: Home Page"]
    TG --> C1["Controller: Checkout Steps"]
    C1 --> P1["Pre-Processor under the controller: runs before each sampler inside it"]
    C1 --> S2["Sampler: Add Address"]
    C1 --> S3["Sampler: Pay"]
    S3 --> P2["Pre-Processor under one sampler: runs only before Pay"]
FIG 2 · Scope depends on the parent of the Pre-Processor.
Where it is placedWhich samplers it preparesTypical use
As a child of one samplerOnly that samplerA special value needed by one request
Under a controllerEvery sampler inside that controllerPreparation shared by a group of steps
Under a thread groupEvery sampler in that groupPreparation for the whole user journey
Directly under the Test PlanEvery sampler in every groupA global rule, used with great care

Wide scope is convenient and costly

A Pre-Processor with a wide scope runs again and again, once before every sampler in its reach. If it does heavy work, such as a database query, that work repeats for every single request. Place each Pre-Processor as close as possible to the samplers that truly need it.

Everyday analogy

A school rule posted at the front gate applies to every classroom. A note on one classroom door applies to that room only. A rule on a single desk applies to one child. Wider rules are easy to write but affect many more people.

TThe Family of Pre-Processors

The Pre Processors menu holds several tools, each with a different job.

When you open the menu, you will see a short list of Pre-Processors. The exact list depends on your JMeter version, but the main members have been stable for many years. Here is a first overview before we study each one.

Data

User Parameters

Gives each virtual user its own set of variable values from a small table you fill in.

Data

RegEx User Parameters

Builds variables from the results of a regular expression extractor, matching names and values.

URL

HTTP URL Re-writing Modifier

Adds a session identifier to web addresses when a site keeps the session in the address instead of in a cookie.

Database

JDBC PreProcessor

Runs a database statement before the sampler and can store the result in variables.

Script

JSR223 PreProcessor

Runs a short script written in a supported language to do any custom preparation.

Script

BeanShell PreProcessor

An older scripting option that is generally recommended against in favour of JSR223.

Limit

Sample Timeout

Interrupts a sampler that runs longer than a time you set.

Links

HTML Link Parser

Reads links from the previous response and uses one of them for the next request.

Everyday analogy

A kitchen drawer holds a peeler, a grater, a whisk, and a timer. You never use all of them for one dish, and you would not peel an onion with a whisk. Pre-Processors are kitchen tools: choose the one that fits the task.

i
Tip

If you are unsure which tool to use, start with the simplest one that can do the job. User Parameters or a script-free solution is easier to read and to repair than a custom script.

i
Version note

Menu names and the presence of older elements vary between versions. Check the menu in your own installation, and treat this guide as a map of ideas.

UUser Parameters: Different Values for Different Users

The simplest way to give each virtual user a personal set of values.

The User Parameters element holds a small table. Each row is a variable name, and each column after the name holds the values for one virtual user. When a thread runs, JMeter picks the column that matches that thread and sets the variables to those values. One user might get the name “alice” and another “bob”, from the same element.

How the table works

1

Name the variables

Add one row for each variable, such as a user name and a city.

2

Add a column per user

Each extra column holds one set of values. Add as many columns as you want distinct users.

3

Use the variables

Refer to the variable names in later samplers with the usual dollar-and-brackets form.

4

Decide when values update

A check box called Update Once Per Iteration controls whether values change on every pass or only once per loop of the thread’s journey.

Everyday analogy

It works like a seating plan for a wedding. Each guest has a card, and when they arrive they receive the card meant for them. The table of cards is written once, and each guest picks up only their own.

When it is a good choice

  • You have a handful of users or values, so a small table is easy to read.
  • The values do not need to change while the test runs.
  • You want something simple that other team members can understand at a glance.
!
Watch out

When there are more virtual users than columns, columns are reused, so several users share the same values. For large numbers of distinct users, a CSV Data Set Config reading a file is usually a better fit.

RRegEx User Parameters: Turning Captured Values into Variables

It reads names and values from an earlier extraction and creates matching variables.

Sometimes a reply contains a whole list of fields that the next request must send back, such as the hidden fields of a web form. Writing one extractor per field is tedious. The RegEx User Parameters element handles this pattern. It looks at the results of an earlier Regular Expression Extractor and turns pairs of captured text into variables.

The three settings that matter

SettingWhat it tells JMeter
Regular Expression Reference NameThe reference name of the earlier extractor whose results should be used
Parameter names group numberWhich group in the match holds the name of each field
Parameter values group numberWhich group in the match holds the value of each field

An idea in plain words

Suppose a page contains many hidden fields, each with a name and a value. An extractor captures every pair. This Pre-Processor then creates one variable per pair, named after the field, holding the field’s value. The next request can send all of them without you writing a line for each.

Everyday analogy

Imagine copying every line of a printed form into a new form with the same boxes. You could write each box by hand, or you could use carbon paper that copies them all at once. This element is the carbon paper.

i
Tip

It depends on an extractor placed earlier, so test the extractor on its own first. If the extractor finds nothing, this element has nothing to turn into variables.

UHTTP URL Re-writing Modifier: Sessions in the Address

When a site keeps your session inside the web address, this element adds it for you.

Most websites remember a visitor using a cookie, which is a small piece of data the browser sends back automatically. JMeter handles cookies through the HTTP Cookie Manager. A few older or special systems instead place a session identifier inside the web address itself. Each page link then ends with a long code that identifies the visitor. If the test does not copy that code into each new address, the server treats every request as a stranger.

What the modifier does

The HTTP URL Re-writing Modifier looks for the session identifier in the previous response, using a name you provide. It then appends that identifier to the addresses of the following requests. You tell it the name of the argument, and optionally whether the identifier is added as a path extension or as an ordinary parameter, and whether to remember it for later use.

Setting

Session Argument Name

The name of the session identifier that the site uses in its addresses.

Setting

Path Extension

Chooses whether the identifier is attached to the path, in the style used by some Java servers.

Setting

Cache Session Id

Remembers the last found identifier, so pages that do not repeat it still receive it.

Setting

URL Encode

Encodes special characters in the identifier so the address stays valid.

Everyday analogy

Think of a cinema ticket that is stamped on your hand instead of kept in your pocket. Each time you enter a screening room you must show the stamp. The modifier carries the stamp from room to room for the virtual user.

i
Production note

Today most systems use cookies or tokens in headers. If your site does, this element is not needed, and adding it only adds work. Check how your application really tracks sessions before choosing it.

JJDBC PreProcessor: Fetching Data from a Database

Run a database statement just before a request and keep the answer in variables.

JDBC stands for Java Database Connectivity, the standard way for Java programs to talk to databases. The JDBC PreProcessor lets a test run a statement against a database right before a sampler, for example to read a fresh order number or to prepare test data. It works together with a JDBC Connection Configuration element, which holds the connection details and gives the connection pool a name.

Main settings in plain words

SettingPlain meaning
Pool nameWhich prepared database connection to use
Query typeWhether it reads, writes, or runs a stored routine
Query textThe statement to run
Variable namesNames for the variables that receive the returned columns
Result variableA variable holding the full result set for later use
Query timeoutHow long to wait before giving up on the statement
Everyday analogy

Before cooking, a chef may phone the warehouse to ask which ingredient is fresh today. The answer decides what goes into the pan. The database call is that phone call, made just before each dish.

Use it with respect

  • Point it at a test database, never at real customer data.
  • Remember that it runs before every sampler in its scope, so keep the scope small.
  • Prefer fetching a block of data once at the start, when the data does not change per request.
  • Be aware that database work competes with the system under test if both share a server.
!
Watch out

Statements that change data can interfere with each other when many users run at once. Test them with a few users first, and consider whether they could lock rows or create duplicates.

JJSR223 PreProcessor: Custom Preparation with a Script

When nothing else fits, a short script can prepare anything.

JSR223 is a standard that lets Java programs run scripts in other languages. The JSR223 PreProcessor runs a short script before the sampler. The script can read and write variables, build values, compute signatures, pick random entries, or adjust the sampler. The JMeter documentation generally recommends JSR223 with the Groovy language for scripting, because it is fast when its compiled form is cached.

Main settings in plain words

  • Language: which scripting language to use. Groovy is the usual choice.
  • Parameters: optional text passed to the script, so one script can serve several elements.
  • Script file: an optional file to run instead of text typed in the screen.
  • Script: the script text itself.
  • Cache compiled script: a check box that lets JMeter compile the script once and reuse it, which matters greatly for speed.
Everyday analogy

A multi-tool pocket knife can do many jobs, but it is slower and clumsier than the right specific tool. A script is the multi-tool of JMeter: flexible, never the first choice when a simple element would do.

When a script is worth it

Good reasons

  • A value needs real calculation, such as a signature or a checksum
  • Logic depends on several variables at once
  • No built-in element offers the needed behaviour

Poor reasons

  • You are more comfortable writing code than using the screens
  • A built-in element already does the job
  • The script is long and nobody else can read it
i
Tip

Keep scripts short, named by purpose, and commented in plain words. A script that only its author understands becomes a risk the day that person leaves.

BBeanShell, Sample Timeout, and HTML Link Parser

Three more members of the family, each with a narrow job.

BeanShell PreProcessor

BeanShell is an older scripting engine that came with JMeter for many years. The BeanShell PreProcessor runs a script before a sampler, much like the JSR223 version. The documentation advises that JSR223 elements are the better choice, mainly because they perform better and are better supported. You will meet BeanShell in older test plans, and it is fine to leave a working one alone, but new work should use JSR223.

Sample Timeout

The Sample Timeout element sets a time limit, in milliseconds, for the sampler it prepares. If the sampler runs longer than the limit, JMeter interrupts it. This is useful when a request might hang forever and you prefer to record a failure and move on. Not every kind of sampler can be interrupted cleanly, so check the behaviour with your own samplers.

Everyday analogy

A chess clock sets a limit on each move. When the time is up, the move is over, whether the player is ready or not. The Sample Timeout is the chess clock for a request.

HTML Link Parser

The HTML Link Parser reads the links, forms, and images found in the previous response and chooses one of them to fill in the next HTTP request. It is mostly used for simple “click around the site” spidering tests, where you do not know in advance which links exist. It is a blunt instrument, because a random click is not a realistic user journey, so many production tests prefer carefully scripted paths.

ElementBest forLimit to remember
BeanShell PreProcessorMaintaining older plansSlower than the recommended JSR223 option
Sample TimeoutStopping requests that might hangOnly works where the sampler can be interrupted
HTML Link ParserQuick random browsing of a siteRandom links are not realistic journeys
i
Production note

A timeout turns an endless wait into a recorded failure, which keeps virtual users flowing. Choose its value from the longest delay a real user would tolerate, not from a guess.

VVariables and Properties: How Pre-Processors Pass Data

Almost every Pre-Processor works by putting a value somewhere that the sampler can read.

JMeter has two main places to keep named values. Variables belong to a single virtual user, which JMeter calls a thread. Properties belong to the whole JMeter program and are shared by every thread. A Pre-Processor usually writes variables, because the preparation is personal to one user’s next request.

FeatureVariablesProperties
Who can see the valueOnly the thread that set itEvery thread in the test
Typical useUser name, token, order number for one userSettings such as the server name or a global limit
How you read it in a requestDollar sign with curly brackets around the nameA special function that reads a property by name
Can it change during the testYes, freely, per threadPossible, but usually set once
RiskLow, because it is privateHigher, because changes affect everyone
Everyday analogy

A variable is a note in your own pocket. A property is a notice on the office wall. Notes in a pocket can change as often as you like without bothering anyone, while a change to the wall notice affects every person who reads it.

How the sampler reads what was prepared

When a sampler runs, JMeter looks through its settings for variable references and replaces each one with the current value. This happens at the moment the sampler runs, which is why a Pre-Processor that sets a variable just before can influence what is sent. The earlier the value is set, the more samplers can use it, but variables set by one thread are never seen by another.

i
Tip

Choose clear names for variables, such as the purpose of the value, and use a short prefix for each area of the test. Dozens of variables with vague names make plans very hard to read.

CPre-Processors Compared with Config Elements

Config Elements set the stage once. Pre-Processors prepare each scene.

Config Elements supply defaults and data sources. Examples include HTTP Request Defaults, which gives every request the same server name, the CSV Data Set Config, which reads rows from a file, and the Counter, which counts upwards. They run before Pre-Processors in the order of execution, and they are often a simpler answer than a Pre-Processor.

QuestionConfig ElementPre-Processor
When does it run?Before Pre-Processors for each sampler in scopeAfter Config Elements, before Timers and the sampler
Main jobProvide defaults and dataPrepare or modify the specific request
Typical exampleRead the next row of a data fileCompute a value from several variables
Can it change the request itself?Mostly by merging defaultsYes, in many cases
Easier to read?Usually yesDepends on the element
Everyday analogy

A theatre company sets the stage furniture before the show begins. Between scenes, a stagehand adjusts a few props. The furniture is the Config Element. The quick adjustments are the Pre-Processors.

A good rule of thumb

If the value comes from a file, a counter, or a random range, look for a Config Element first. If the value needs a decision, a calculation, a lookup, or a change to the request that is about to go, use a Pre-Processor. Using the simplest element that works keeps the plan lighter and easier to teach to new team members.

i
Production note

Plans that grow over years often end up with scripts doing jobs that a Config Element could do with no code. A short review of old scripts can remove surprising amounts of risk and maintenance.

CPre-Processors Compared with Timers and the Setup Thread Group

Three ways to do something before a request, each with a different meaning of “before”.

Beginners often reach for a Pre-Processor when another element would do better. Two close neighbours are the Timers and the Setup Thread Group.

Timers

A Timer adds a pause before its sampler runs. It does not change the request. Timers run after Pre-Processors, so the preparation is already finished by the time the pause begins. Use a Timer when the only thing you need before the request is to wait.

The Setup Thread Group

A Setup Thread Group is a special group that runs once, before the normal thread groups start. It is meant for one-time preparation, such as creating test accounts or clearing old data. A Pre-Processor, by contrast, runs again and again, before every sampler in its scope.

NeedBest fitWhy
Different value for each user at each requestPre-ProcessorRuns per thread, per request
Create data once before the test beginsSetup Thread GroupRuns a single time before the main groups
Wait between requestsTimerDesigned for pauses
Same value shared by everybodyProperty or Config ElementComputed once, read many times
Clean up after the testTeardown Thread GroupRuns once after the main groups
Everyday analogy

Before a football match, the groundskeeper marks the pitch once for everyone. Each player ties their own boots before kick-off. The Setup Thread Group is the groundskeeper. The Pre-Processors are the players tying their own laces.

!
Watch out

Doing heavy one-time work in a Pre-Processor means repeating it for every request. If a task only needs to run once, move it to the Setup Thread Group.

TTwo Ends of a Request: Pre-Processors and Post-Processors

One prepares the request. The other studies the answer.

A Post-Processor runs after the sampler has received its response. It usually reads the response and captures values, such as a token or an identifier. The most famous Post-Processors are the extractors: the Regular Expression Extractor, the JSON Extractor, the CSS Selector Extractor, and the XPath Extractor. They capture values into variables.

A Pre-Processor and a Post-Processor often work as a pair. The Post-Processor of one step captures a value. The Pre-Processor of a later step may prepare it for use. Understanding this partnership clears up most of the confusion about the two types.

FeaturePre-ProcessorPost-Processor
RunsBefore the samplerAfter the response arrives
Looks atThe request about to be sent, and variablesThe response that came back
Typical outputPrepared variables and modified requestsCaptured variables
Typical exampleUser Parameters, JDBC PreProcessorRegular Expression Extractor
Skipped when the sampler produces no resultNo, it already ranYes, nothing to process
Everyday analogy

A relay race has a runner who prepares the baton hand-off and a runner who receives it. One leg ends when the baton is passed, and the next leg begins with the received baton. The Post-Processor receives the value, and the Pre-Processor of the next step makes use of it.

i
Tip

When a value comes out of a response, think extractor. When a value must be prepared before sending, think Pre-Processor. When both are needed, use both, in that order.

TThread Safety and Per-User Data

Many users run at once, so shared values need special care.

JMeter runs each virtual user in its own thread, a separate line of work inside the program. Many threads run at the same moment. A property of thread safety means a piece of code behaves correctly even when many threads run it at the same time. Variables set by a Pre-Processor are private to one thread, so they are naturally safe. Problems appear when threads share something.

Where sharing creates trouble

Risk

Shared files

Two threads picking the same row from a data file may use the same account at the same time.

Risk

Shared properties

One thread changing a property can surprise another thread that is reading it.

Risk

Shared database rows

Two threads updating the same row can block or overwrite each other.

Risk

Shared counters in scripts

A global count updated by many threads can lose or duplicate numbers without protection.

Everyday analogy

Imagine a classroom where every pupil has their own notebook. Nobody interferes with anyone else. Now imagine one shared notebook on a single desk, where everybody scribbles at once. The writing becomes a mess. Variables are the private notebooks. Shared properties are the single desk.

Simple habits that keep things safe

  • Prefer variables over properties for per-user data.
  • Use built-in elements, such as the Counter, which are designed with threads in mind.
  • Give each user separate data where possible, so threads never fight for the same row.
  • If a script must share something, keep that part tiny and protect it with the language’s standard tools for safe sharing.
i
Production note

Thread safety bugs are among the hardest to find, because they appear only under real load and only sometimes. A plan that works perfectly with one user can behave oddly with two hundred.

HHow a Pre-Processor Works Internally

Follow one request from the moment it is chosen to the moment it leaves.

When a virtual user reaches a sampler in its journey, JMeter assembles all the elements in scope, sorts them by type, and runs them in the fixed order we met earlier. The steps below show what happens around the Pre-Processors.

sequenceDiagram
    participant T as Virtual User Thread
    participant C as Config Elements
    participant P as Pre-Processors
    participant M as Timers
    participant S as Sampler
    participant V as Server
    T->>C: Apply defaults and data sources
    C-->>T: Variables and defaults ready
    T->>P: Run each Pre-Processor in scope
    P-->>T: Variables set, request adjusted
    T->>M: Apply timers
    M-->>T: Pause completed
    T->>S: Run the sampler
    S->>V: Send the prepared request
    V-->>S: Response
FIG 3 · The path of one request, with Pre-Processors before the timer and sampler.
1

The thread reaches a sampler

Control moves to the next sampler in the journey, perhaps after a controller has decided it should run.

2

JMeter collects the elements in scope

It gathers every Config Element, Pre-Processor, Timer, Post-Processor, Assertion, and Listener that applies to this sampler.

3

Pre-Processors run in tree order

Among Pre-Processors, those that appear earlier in the tree run first. Their changes accumulate, so a later one can use what an earlier one set.

4

Variables are resolved

When the sampler runs, every variable reference in its settings is replaced with its present value.

5

The request leaves

The sampler sends the final, prepared request to the server and waits for the answer.

Everyday analogy

Think of a pilot’s pre-flight checklist. Items are completed in a set order, each building on the last, before the aircraft is allowed onto the runway. The sampler is the take-off, and the Pre-Processors are the checklist.

i
Tip

Because Pre-Processors of the same type run in tree order, you can arrange two of them so that the second uses the output of the first. Keep such dependencies obvious with clear names.

DData Flow and Lifecycle Across Iterations

A thread repeats its journey many times, and preparation repeats with it.

A thread group tells each virtual user how many times to repeat its journey. Each repetition is called an iteration. In each iteration, each sampler runs again, and so do the Pre-Processors in its scope. The values they set therefore change with every loop, unless the element is told to update only once.

The life of a variable across a test

MomentWhat happens to a prepared variable
Thread startsThe thread begins with its own empty set of variables
First iterationPre-Processors set values, and samplers use them
Next iterationValues are set again, or kept if the element updates once per iteration
A later step needs an earlier valueThe variable remains available until it is overwritten
Thread endsThe variables are discarded with the thread
Everyday analogy

A waiter takes a fresh order pad to each table. At the end of the evening the pads are thrown away. Nothing from table one leaks onto table five, but the waiter can still refer to what was written earlier on the same table.

A stale value is a silent problem

Because a variable stays set until it is changed, a value from a previous iteration can accidentally be reused when the new preparation fails. The request then goes out with yesterday’s data, and nothing complains. Protect against this by clearing or resetting variables at the start of each iteration, where it matters, and by checking for the expected value in an assertion.

!
Watch out

If a Pre-Processor fails silently, the sampler may still run using an older value. A test that looks healthy can be sending stale data. Assertions that check for the right response guard against this.

CCorrelation: When an Extractor Feeds a Pre-Processor

Correlation is the art of carrying a value from one response into the next request.

Modern web applications are full of values that change on every visit: session tokens, form tokens, order identifiers, and security codes. A test that replays a recorded request with an old value fails, because the server expects the fresh one. The technique of capturing the fresh value and sending it back is called correlation.

The usual partnership

1

Step one returns a value

The response contains a token or identifier that will be needed later.

2

A Post-Processor captures it

An extractor stores the value in a variable.

3

A Pre-Processor may reshape it

If the value must be modified, combined, or encoded, a Pre-Processor does that just before use.

4

The next sampler sends it

The request refers to the variable, and JMeter fills in the fresh value.

Everyday analogy

A hotel gives you a room key card at check-in. Each time you open your door, you must present that very card, not a copy from last year. Correlation is the habit of carrying today’s card to every door.

i
Production note

Many production test failures come from missed correlation: a token that was recorded once and replayed forever. Whenever a request works once but fails under load or on repeat, look for a value that should have been fresh.

CChoosing the Right Pre-Processor

A few questions lead you to the simplest tool that works.

flowchart TD
    A["I need something prepared before a request"] --> B{"Is it a data file or counter?"}
    B -- "Yes" --> C["Use a Config Element such as CSV Data Set Config"]
    B -- "No" --> D{"Do users need different fixed values from a small table?"}
    D -- "Yes" --> E["Use User Parameters"]
    D -- "No" --> F{"Does the site put the session in the address?"}
    F -- "Yes" --> G["Use HTTP URL Re-writing Modifier"]
    F -- "No" --> H{"Is the value stored in a database?"}
    H -- "Yes" --> I["Use JDBC PreProcessor, or fetch once in Setup Thread Group"]
    H -- "No" --> J{"Must I limit how long a request may run?"}
    J -- "Yes" --> K["Use Sample Timeout"]
    J -- "No" --> L["Use JSR223 PreProcessor with a short script"]
FIG 4 · A simple decision path for picking a Pre-Processor.

Why this order of questions

The questions move from the simplest tool to the most flexible. Config Elements need no code. User Parameters need only a table. Special-purpose elements do one thing well. A script is last because it can do anything, and anything is also hard to read, test, and maintain.

Everyday analogy

When something is broken at home, you first try a screwdriver, then a wrench, and only after that do you call a builder with a van full of tools. Try the simple fix first.

i
Tip

Whenever you choose a script, write one sentence in the comments that says why no built-in element was suitable. The sentence helps the next reader judge whether the script is still needed.

CA Cookbook of Preparation Tasks

Common needs and the usual element that serves them.

TaskUsual elementNotes
A different user name for each virtual userCSV Data Set Config or User ParametersUse a file for large numbers, a table for small sets
A fresh time stamp in each requestA built-in time function, or a short scriptFunctions are enough for simple needs
A random choice from a listA random function or a short scriptKeep the list small and clear
A unique reference numberCounter or a unique-identifier functionCheck the format the system expects
Session identifier in the addressHTTP URL Re-writing ModifierOnly for sites that use it
A hidden form with many fieldsRegEx User Parameters after an extractorTest the extractor first
A value looked up from a databaseJDBC PreProcessorPrefer fetching once when possible
A computed signature or checksumJSR223 PreProcessorUse a well-known standard library
A limit on how long a request can runSample TimeoutChoose from real user tolerance
Clicking a random link on a pageHTML Link ParserNot a realistic journey
Everyday analogy

A recipe book lists which tool suits which job: a whisk for eggs, a knife for onions. A cookbook for tests does the same, and saves you from using the wrong tool out of habit.

i
Production note

JMeter also includes many built-in functions that can be written directly in a request, such as time, random, and unique-identifier functions. For simple needs, a function in the request field is lighter than any Pre-Processor at all.

TTime Stamps, Random Values, and Unique Identifiers

Three kinds of fresh values appear in almost every real test.

Time stamps

A time stamp is a number or text that records a moment. Many systems expect a current time in each request, either to reject old requests or to sign them. A prepared time stamp should be created just before sending, because a stamp prepared too early may expire by the time the request arrives. Time zones and formats matter, so check what the server expects.

Random values

A random value is chosen by chance within a range. Random choices make a test less repetitive: a random product, a random quantity, a random search word. Two cautions apply. Real traffic is rarely perfectly random, because popular items are chosen far more often than rare ones. And purely random choices can make results hard to reproduce, so many teams use a fixed starting value for repeatable runs.

Unique identifiers

A unique identifier is a value that should never repeat, such as an order number or a new account name. Many systems reject duplicates. Counters and standard unique-identifier functions are the safest sources. Hand-made values from random numbers can collide when thousands of threads run together.

Time

Create it late

Prepare time stamps as close to sending as possible, so they stay fresh.

Random

Mimic real habits

Weight the choices towards popular items if your real users behave that way.

Unique

Use proven sources

Rely on counters or unique-identifier functions instead of inventing your own scheme.

Everyday analogy

A time stamp is the date on a milk carton, which is useless if printed last month. A random value is picking a card from a deck. A unique identifier is a numbered raffle ticket, where two tickets with the same number would cause a quarrel.

!
Watch out

Clocks differ between machines. If the system under test compares time stamps with its own clock, a load generator whose clock is minutes off can cause strange rejections that look like application bugs.

WWhat Happens When a Pre-Processor Fails

A quiet failure in preparation can produce loud, confusing errors later.

Preparation steps can fail. A script may hit an unexpected value. A database may be unreachable. A table may be missing a column. What JMeter does next depends on the element and on the kind of failure, but a general pattern is common: the problem is written to the log file, and the sampler may still run with whatever values happen to be available. Check the behaviour of your own version and elements, instead of assuming.

The chain of confusion

1

Preparation fails

The Pre-Processor cannot set the value it was meant to set.

2

The sampler still runs

It sends the request with an old value, an empty value, or the unreplaced variable name itself.

3

The server complains

It returns an error, a login page, or a message about missing data.

4

You look in the wrong place

The error appears on the sampler, so you suspect the server, though the cause lay one step earlier.

Everyday analogy

If a baker forgets to add yeast, the bread comes out flat, and the customer blames the oven. The real fault was in the preparation, long before the baking.

How to guard against it

  • Add assertions that check for correct responses, so bad requests are marked as failures.
  • Set a clear default for important variables, so a failed step produces an obvious value instead of a misleading blank.
  • Read the log file after every run, and look for errors from the elements you added.
  • In scripts, check for missing data and write a short log line that names the step.
!
Watch out

When a request contains the literal text of a variable name, including the dollar sign and brackets, it means the variable was never set. This is one of the quickest signs that a preparation step did not run or failed.

DDebugging Pre-Processors

You cannot see preparation directly, so you need windows into it.

A Pre-Processor does not appear in the results, so debugging means looking at what it did: which variables it set, what the request looked like when it left, and what the log says. JMeter offers several friendly tools for this.

Tool

View Results Tree

Shows the exact request each sampler sent, so you can check whether prepared values arrived.

Tool

Debug Sampler

Produces a result listing the current variables, properties, and system values at that point in the journey.

Tool

Debug PostProcessor

Adds variable and property details to the result of a sampler, useful right after a step you want to inspect.

Tool

The log file

Records errors and any messages written by your scripts. Always read it after a failed run.

A calm routine

1

Run with one user

Remove the noise of many threads. Use a single user and a single loop.

2

Look at the sent request

In View Results Tree, open the request tab and compare the real values with what you expected.

3

Inspect the variables

Insert a Debug Sampler just before the suspect step and read the variable list.

4

Read the log

Look for error lines from the element you are checking.

5

Scale up slowly

Add a few users, then more, to find problems that appear only with sharing.

Everyday analogy

A plumber who cannot see inside the wall listens at the pipe, checks the meter, and looks at the tap. Debugging preparation is the same: you inspect what comes out and what was recorded, because you cannot watch the inside directly.

i
Tip

Remove or disable debug elements before a real test. They create results of their own and add cost, so they belong to the building stage only.

PPerformance Cost of Preparation

Every preparation step uses the same machine that is generating your load.

The load generator has a limited amount of processor power. Time spent preparing a request is time not spent sending or receiving. For a few users this is invisible. When thousands of threads run, small costs multiply, and a slow Pre-Processor can reduce the load you can generate or distort the measurements.

Where the costs hide

Source of costWhy it mattersRemedy
Scripts compiled on every runCompiling is slow and repeats for every requestUse JSR223 with the compiled-script cache enabled
Older script enginesBeanShell is generally slower than JSR223Move new and busy scripts to JSR223 with Groovy
Database calls per requestAdds network time and database loadFetch data in advance when possible
Wide scopeThe element runs before every sampler in reachNarrow the scope to the samplers that need it
Heavy work in scriptsLarge loops or string building burn processor timeKeep scripts small and prepare data ahead of time
Excessive loggingWriting many lines per request slows the generatorLog only warnings and errors in real runs
Everyday analogy

A taxi driver who stops to fill in a form before every passenger gets fewer fares per hour. Preparing a request is the form. A short form is fine. A long form on every trip loses money.

Measuring the cost

The simplest check is to run the same test with and without the Pre-Processor, for the same number of users, and compare throughput and processor use on the generator. If throughput drops or processor use climbs sharply, the preparation is expensive. Run such comparisons in a quiet environment and repeat them, because single runs can mislead.

i
Production note

A useful rule of thumb is that the load generator should have spare capacity. If it runs near its limit, you are measuring your generator as much as your system.

SScalability and Distributed Testing

When one machine is not enough, preparation must work on many machines at once.

A single JMeter machine has limits. To generate more load, teams use distributed testing, in which a controller directs several other machines, called remote engines or workers. Each worker runs its own copy of the test plan. This has important consequences for preparation.

Things that change when you distribute

Data

Data files are per machine

Each worker reads its own copy of a data file, so the same row can be used on several machines unless you split the file.

Variables

Variables stay local

A variable set on one worker is invisible to the others, which is usually what you want.

Properties

Properties need care

Properties belong to one worker’s program. Setting one on a worker does not change the others.

Counters

Counters repeat

Each worker counts on its own, so two machines can produce the same number unless you give them different starting points.

Everyday analogy

Imagine ten branches of a bank, each with its own numbered ticket machine. Without coordination, branch three and branch seven will both call out “ticket 42”. If the numbers matter across branches, each branch needs its own range.

Habits that scale

  • Split data files so each worker receives different rows.
  • Give each worker its own numeric range for counters and unique identifiers.
  • Pass settings to each worker through properties set when it starts.
  • Keep preparation cheap so each worker can spend its power sending requests.
  • Check each worker with a tiny run before the real test.
i
Tip

Duplicate accounts are the classic distributed testing surprise. If two workers log in as the same user at the same time, the system may log one out, and you will chase a problem that your own setup created.

LLarge Data Sets and Memory

Preparation data that is too big for memory causes slow tests and strange failures.

Some tests need thousands or millions of distinct values: accounts, products, search words. A few ways of holding that data are cheap, and others are very expensive. The choice affects how much memory the load generator needs.

ApproachMemory behaviourGood for
CSV Data Set Config reading a fileReads rows as needed, light on memoryLarge lists of accounts or values
User Parameters tableStored in the plan, grows with every columnA handful of users
Script that loads a whole file into memoryHolds all values for every thread, or one copy at bestSmall lists only
Database query per requestLight on the generator, heavier on the databaseData that changes constantly
Everyday analogy

A librarian can carry a single book to a reader, or wheel the entire library into the reading room. A file read on demand is the single book. Loading everything into memory is the whole library on a trolley.

Habits that save memory

  • Keep large lists in files and read them with the data file element.
  • Avoid storing large values, such as whole responses, in variables unless needed.
  • Release or overwrite large variables when they are no longer useful.
  • Give the JMeter program enough memory, and watch it during the run.
!
Watch out

An out-of-memory failure in the middle of a long test wastes hours. Run a short rehearsal at full user count first, and watch memory, before committing to the long run.

MMonitoring, Logging, and Metrics

Preparation leaves no rows in the results, so you must watch it another way.

Because Pre-Processors do not produce results, a healthy-looking report can hide preparation problems. The solution is to observe preparation through logs, through the requests that came out, and through the health of the load generator.

flowchart LR
    PP["Pre-Processors"] --> RQ["Prepared request"]
    PP --> LG["JMeter log file: warnings and errors"]
    RQ --> SV["System under test"]
    SV --> RS["Results file"]
    RS --> RP["Report: errors, percentiles, throughput"]
    GH["Generator health: CPU, memory, network"] --> DB["Dashboard"]
    LG --> DB
    RP --> DB
FIG 5 · Where to look for signs that preparation is working or failing.

What to watch

  • The log file: errors from scripts, database calls, and missing variables.
  • The error rate: sudden jumps often mean prepared values went bad.
  • Request details for a sample: a few recorded requests, to confirm the values look right.
  • Generator health: processor, memory, and network, to see whether preparation is costly.
  • Database load: if a database Pre-Processor is used, check its effect on the database.
Everyday analogy

A restaurant manager cannot taste every dish, but can read the order tickets, listen for complaints, and check that the kitchen is not overheating. Each is an indirect view of the preparation.

i
Production note

Mark in your records when each run started and stopped, and which version of the plan was used. When something looks odd later, those notes let you compare against a known good run.

SSecurity Considerations

Preparation often touches credentials, databases, and scripts, so it deserves extra care.

Pre-Processors handle some of the most sensitive material in a test: user names, passwords, tokens, connection details, and scripts that can do almost anything. A test plan can be shared, stored, and copied, so secrets inside it travel with it.

SECURITY CHECKLISTReview
Before the test

Use test accounts and test data, never real customers. Keep passwords and connection details out of the plan text where possible, and supply them through protected settings at run time. Make sure you have permission to test the target.

During the test

Limit what scripts can reach. Avoid logging passwords or tokens, because log files are widely readable. Point database elements only at test databases.

After the test

Remove test accounts and data that were created, secure or delete result and log files, and review the plan for leftover secrets before sharing it.

Specific risks

  • Scripts run with the power of the JMeter program. A plan from an unknown source may contain scripts that read files or call other systems, so review before you run it.
  • Database Pre-Processors can change real data if pointed at the wrong server, so double-check connection details.
  • Tokens and passwords in plans can leak through shared files, screenshots, and version control history.
  • Load can look like an attack. Always notify the owners of the system and test only what you are allowed to test.
Everyday analogy

A set of keys left in a shared drawer can open every door in the building. Credentials in a test plan are keys in a drawer. Keep the drawer locked, and hand out only the keys that are needed.

!
Watch out

Never run a test plan received from an unknown source without reading its scripts first. A script element is code that executes on your machine.

AAdvantages, Disadvantages, and Trade-offs

Preparation makes tests realistic, and it costs effort and complexity.

Advantages

  • Makes each virtual user behave like a distinct person
  • Keeps tokens, sessions, and identifiers fresh
  • Prepares requests close to the moment they are sent
  • Scope controls let you target exactly the samplers that need it
  • A wide choice of elements, from no-code tables to full scripts
  • Works naturally with extractors for correlation

Disadvantages

  • Invisible in the results, so failures are easy to miss
  • Runs again for every sampler in scope, so cost multiplies
  • Scripts can become hard to read and maintain
  • Shared data and properties create thread safety risks
  • Database elements can load the very systems under test
  • Order of execution surprises beginners
Trade-offWhat you gainWhat you give up
Script instead of a built-in elementTotal flexibilityReadability and speed of maintenance
Per-request preparationFresh values every timeProcessor time on the generator
Preparing in advance, in a setup stageLow cost during the testValues may be stale or limited
Wide scopeFewer elements to maintainUnnecessary work on samplers that do not need it
Random valuesVariety and less cachingHarder to reproduce a run exactly
Everyday analogy

Preparing a meal fresh to order tastes best but needs more hands in the kitchen. Preparing everything in advance is faster at serving time but the food may sit too long. Each choice buys something and costs something.

i
Production note

The best plans prepare as little as realism requires. Every extra step is something that can fail, slow down, or confuse the next reader.

PDesign Patterns for Preparation

Good habits repeat across good test plans.

Pattern

Prepare as close as possible

Place each Pre-Processor as near as possible to the samplers that use it, so scope stays small and the plan stays readable.

Pattern

Simple first

Prefer Config Elements, functions, and tables over scripts. Move to a script only when nothing simpler fits.

Pattern

Fetch once, reuse many

If data does not change per request, read it in a setup stage or from a file, instead of querying it before every sampler.

Pattern

Verify what you prepared

Pair every critical preparation with an assertion on the response, so a failed step shows up as a failure.

Pattern

Name by purpose

Give each element a name that says what it prepares, such as “Set session token for checkout”.

Pattern

One job per element

Keep each Pre-Processor focused on a single task, so problems are easy to locate.

A pattern called “Prepare, Send, Capture, Check”

1

Prepare

A Pre-Processor or Config Element makes the request ready.

2

Send

The sampler sends it to the server.

3

Capture

A Post-Processor stores any values needed later.

4

Check

An assertion confirms the response was correct.

Everyday analogy

A good mail clerk prepares the envelope, posts it, files the receipt, and confirms delivery. Doing all four steps, in order, is what makes the whole job dependable.

AAnti-patterns to Avoid

Some habits look clever and cause trouble later.

ANTI-PATTERN 01Avoid
The pattern

Putting a heavy Pre-Processor, such as a database lookup, directly under the thread group.

Why it hurts

It runs before every sampler in the group, multiplying database load and slowing the generator.

Better approach

Narrow the scope to the one sampler that needs it, or fetch the data once in a setup stage.

ANTI-PATTERN 02Avoid
The pattern

A single giant script that prepares dozens of values and changes many things at once.

Why it hurts

Nobody else can read it, test it, or safely change it, and one bug breaks everything.

Better approach

Split the work into small, named elements, each with a single clear purpose.

ANTI-PATTERN 03Avoid
The pattern

Using shared properties to hold per-user data.

Why it hurts

Threads overwrite each other, so users receive each other’s values and the test becomes unreliable.

Better approach

Use variables, which are private to each thread.

ANTI-PATTERN 04Avoid
The pattern

Never checking whether preparation succeeded.

Why it hurts

Requests go out with stale or blank values, and the resulting errors look like server faults.

Better approach

Add assertions, set safe defaults, and read the log after every run.

ANTI-PATTERN 05Avoid
The pattern

Hard-coding passwords and tokens in scripts and shared plans.

Why it hurts

Secrets leak through files, screenshots, and history.

Better approach

Supply secrets at run time through protected settings, and use test accounts only.

OOrganising and Maintaining Preparation Elements

A plan that is easy to read stays correct for longer.

Test plans live for years. People join and leave the team, the application changes, and the plan is edited many times. Preparation elements are scattered through the tree and invisible in the results, so they are easy to forget. A little organisation prevents big confusion later.

Habits that help

  • Name every element for its purpose. Avoid default names such as “JSR223 PreProcessor”, which tell the reader nothing.
  • Add comments. Every element has a comments field. Use it for the reason the element exists and the version of the system it was written for.
  • Group related steps under controllers. Putting the preparation near its samplers makes the story of each step easy to follow.
  • Keep scripts in files for reuse. A shared script file avoids copies that drift apart over time.
  • Store plans in version control. A history of changes explains why a plan is the way it is.
  • Review old plans regularly. Remove elements that no longer serve a purpose.
Everyday analogy

A kitchen with labelled jars and neatly placed tools lets a new cook get started at once. A kitchen with unlabelled jars makes every task a guessing game. Names and comments are the labels.

i
Tip

Ask a colleague to read your plan without your help. Wherever they get confused is where a name or a comment is missing.

PProving Your Preparation Works

Preparation is invisible, so you must test it on purpose.

A Pre-Processor that silently does nothing looks exactly like one that works. The only way to know is to check the evidence: the request that was sent, the values that were set, and the responses that came back. A short routine gives you that confidence before you scale up.

1

Run one user, one loop

Open the sent request in the results tree and compare each prepared value with what you intended.

2

Run a few users

Check that different users received different values, where they should, and the same values where they should not differ.

3

Run several loops

Confirm values refresh at each iteration, and that nothing from the previous loop leaks into the next one.

4

Break something on purpose

Remove a data row, change a name, or stop a database in a test environment. Confirm the failure is visible in the log or in an assertion.

5

Rehearse at full size

Run briefly with the full user count and watch memory, processor use, and errors.

ExperimentWhat you should seeIf you do not
Two users, two data rowsDifferent values in each user’s requestsBoth users share a row, or the scope is wrong
Three loops of one userA fresh value in each loopThe element is set to update only once, or an old value is reused
Remove the needed dataA clear error in the log or a failed assertionFailure is silent, so add checks
Rename the variable in the requestThe literal variable name appears in the sent requestThe request does not use the variable at all
Everyday analogy

A fire alarm must be tested by pressing the test button. An alarm that has never been tested is only a hope. A preparation step that has never been seen to fail is the same.

i
Tip

Repeat the routine whenever the application, the plan, or the data files change. A small rehearsal costs minutes and can save a whole night’s run.

TTroubleshooting a Pre-Processor That Misbehaves

Most problems come from a small set of causes. Match your symptom with the table.

SymptomLikely causeWhat to check
The request shows the literal variable nameThe variable was never set, or set after the sampler ranThe scope, the order of elements, and the log for errors
All users send the same valueOne shared column, a shared property, or the same data rowData element settings, sharing mode, and variable use
The value never changes between loopsUpdate-once setting, or a variable that was not resetThe loop settings of the element
Pre-Processor seems not to runIt sits where no sampler is in scopeIts parent in the tree and the enabled state
Wrong order of preparationTwo elements depend on each other but run in the wrong orderTheir order in the tree among elements of the same type
Config value is not changed as expectedConfig Elements run before Pre-ProcessorsMove the change earlier, or use a different element
Test is slower than expectedHeavy script, wide scope, or database call per requestCost of each element and the generator’s processor use
Session identifier missing in addressesWrong argument name, or the site uses cookies insteadHow the application tracks sessions
Database element failsWrong pool name, missing connection element, or wrong query typeThe connection configuration and the log
Script errors on only some requestsUnexpected or missing values for certain usersThe data and the log lines for those users

A method for any puzzle

1

Reproduce it small

Use one user and one loop. If the fault disappears, the cause involves sharing.

2

See the sent request

Compare what was sent with what you expected, field by field.

3

Check the order and the scope

Confirm the element is in scope and runs where you think it does.

4

Read the log

Look for errors from the element in question.

i
Production note

When the sent request is wrong, look at preparation. When the sent request is right but the response is wrong, look at the server. Making that first split saves hours.

AA Worked Example: Signing In and Placing an Order

Follow an imaginary online shop test from sign-in to order.

A team wants to test a shop where many different customers sign in, add an item, and place an order. Each customer needs a distinct account, and each order needs a unique reference. The shop returns a token after sign-in that every later request must carry.

flowchart TD
    D["Data file: one account per user"] --> L["Sampler: Sign In"]
    L --> X["Post-Processor: capture token"]
    X --> P1["Pre-Processor: build unique order reference"]
    P1 --> O["Sampler: Place Order with token and reference"]
    O --> A["Assertion: order confirmation text present"]
    A --> R["Results and report"]
    P1 --> LG["Log shows any preparation errors"]
FIG 6 · Preparation and capture around a sign-in and order journey.
1

Distinct accounts

A data element reads one account for each virtual user from a file, so no two simultaneous users share a sign-in.

2

Sign in and capture

The sign-in request goes out. An extractor captures the token from the response into a variable.

3

Prepare the order reference

Just before the order request, a short, clearly named Pre-Processor builds a unique reference from the user’s identity and a counter, so no two orders collide.

4

Send and check

The order request carries the token and the reference. An assertion confirms the confirmation message appears.

5

Watch and review

After the run, the team checks the log for preparation errors and the report for failures.

What makes this plan healthy

  • The Pre-Processor has a narrow scope, attached only to the order step.
  • It has one job, and a name that says what it does.
  • Its result is verified by an assertion on the response.
  • Values come from proven sources: a data file for accounts and a counter for uniqueness.
i
Production note

This example is imaginary and simplified. Real shops add many more steps, but the habit of preparing narrowly, capturing carefully, and checking every critical response is the same.

CCommon Misunderstandings

Six ideas that beginners often get wrong.

Myth

“Order in the tree is order of execution”

Elements run by type first, then by tree order within the same type. A Pre-Processor always runs before its sampler.

Myth

“A Pre-Processor runs once”

It runs before every sampler in its scope, every iteration. One element can run thousands of times.

Myth

“It appears in the results”

It produces no result row, so problems with it are invisible unless you look at the requests and the log.

Myth

“Variables are shared by all users”

Variables are private to each thread. Only properties are shared across the whole program.

Myth

“A script is always the best answer”

A script is the most flexible tool and the hardest to maintain. Start with simpler elements.

Myth

“If it works for one user it works for all”

Sharing, memory, and timing problems appear only with many users running together.

Everyday analogy

A recipe that works in a small home kitchen may fail in a restaurant, because the stove, the timing, and the helpers all change. A test that works for one user is the home kitchen. A test with a thousand is the restaurant.

A habit that corrects all six

Before you rely on a preparation step, ask three questions. What exactly will it set, and for whom? When will it run, and how often? How will I see that it worked? Honest answers to those three questions expose most misunderstandings before they cost you a run.

!
Watch out

Do not trust a green report alone. Preparation faults often produce quick error pages that look fine in a speed chart. Always pair speed with correctness checks.

BBest Practices and Common Mistakes

A short checklist to carry into your next test.

1

Choose the simplest element

Prefer Config Elements, functions, and no-code tables, and use scripts last.

2

Keep scope narrow

Attach each Pre-Processor to the smallest group of samplers that need it.

3

Use JSR223 with Groovy for scripts

Enable compiled-script caching, keep scripts short, and avoid older engines for new work.

4

Prefer variables to properties

Keep per-user data in variables so threads cannot trample each other.

5

Verify with assertions

Check each critical response so failed preparation shows up as a failure.

6

Read the log after every run

Many preparation faults appear only there.

7

Name, comment, and version

Explain each element’s purpose, and store plans in version control.

8

Protect secrets

Use test accounts, and keep passwords and tokens out of shared files and logs.

Common mistakes in one list

  • Using a heavy Pre-Processor with a wide scope, so it runs far too often
  • Writing long scripts that only one person understands
  • Holding per-user data in shared properties
  • Forgetting that Config Elements run before Pre-Processors
  • Never checking that preparation succeeded
  • Leaving old BeanShell scripts in busy parts of the plan without review
  • Splitting data badly across distributed workers, so users collide
  • Hard-coding passwords and tokens in shared plans
  • Leaving debug elements enabled during a real run
Prepare narrowly, verify always, and keep secrets secret.

RReal-World Scenarios

Five typical situations, described in general terms so you can adapt them.

The cached shortcut

A media site tests its search page with a single fixed search word. The results come back astonishingly fast, because the server caches the answer. After adding a preparation step that picks a different word from a list for every request, the cache stops helping, and the true cost of searching appears. The first test had been measuring the cache, not the search.

The expired token

A banking-style application issues a security token valid for a few minutes. A recorded test replays the token from the recording, and nearly every request after the first is rejected. By capturing a fresh token after each sign-in and preparing it for later requests, the test finally exercises the real journey.

The duplicate account storm

A team distributes a test over four machines, each reading the same data file. Several workers sign in as the same user at once, and the system logs them out. After splitting the file so each worker gets different accounts, the strange logout errors disappear.

The slow script

An old plan uses a long BeanShell script before every request to compute a signature. At high load, the generator’s processor reaches its limit, and throughput stalls even though the server is idle. Moving the logic to a short, cached JSR223 script restores the generator’s speed and exposes the server’s real limits.

The hanging request

A legacy service occasionally never answers. Virtual users wait forever, and the test seems stuck. Adding a time limit to the affected sampler turns each hang into a recorded failure after a fixed time, so the test keeps flowing and the problem becomes visible in the error rate.

Realistic preparation turns a demo into a measurement.

QQuick Reference

A one-page summary you can keep next to your test plan.

TopicSummary
What it isAn element that prepares a request just before the sampler runs
Order of executionConfig Elements, Pre-Processors, Timers, Sampler, Post-Processors, Assertions, Listeners
ScopeSet by the parent in the tree: one sampler, a controller, a group, or the whole plan
Different values per userUser Parameters for small sets, a data file element for large sets
Session in the addressHTTP URL Re-writing Modifier
Values from a databaseJDBC PreProcessor, or fetch once in a setup stage
Custom logicJSR223 PreProcessor with Groovy, compiled script cache on
Limit on request timeSample Timeout
Where results appearNowhere: check the sent request and the log
Per-user dataVariables, not properties
Distributed testsSplit data files, give workers separate ranges, keep preparation cheap
SecurityTest accounts, protected secrets, reviewed scripts

Five questions before pressing start

  • Does every virtual user get the values it needs, and are they different where they should be?
  • Is each Pre-Processor attached to the smallest scope that works?
  • Have I seen the sent request and confirmed the prepared values arrived?
  • Will a failed preparation show up as a failure, through assertions or the log?
  • Are secrets protected, and are debug elements switched off?

FFrequently Asked Questions

Quick answers to the questions beginners ask most often.

Q1What is a Pre-Processor in JMeter?
It is an element that runs just before a sampler and prepares the request, usually by setting variables or adjusting what will be sent.
Q2When does it run compared with other elements?
After Config Elements and before Timers, the sampler, Post-Processors, Assertions, and Listeners.
Q3Does a Pre-Processor run before every request?
It runs before every sampler in its scope, in every iteration. Wide scope means it runs very often.
Q4What is the difference between a Pre-Processor and a Post-Processor?
A Pre-Processor works before the request is sent. A Post-Processor works after the response arrives, typically capturing values from it.
Q5Which Pre-Processor should I use to give each user different data?
Use User Parameters for a small table of values, or a CSV Data Set Config for large lists. Both are simpler than scripts.
Q6Should I use BeanShell or JSR223?
JSR223 with Groovy is generally recommended, mainly for performance. Keep old BeanShell elements working if needed, but write new ones in JSR223.
Q7Why does my request still contain the variable name?
The variable was not set when the sampler ran. Check the scope, the order of elements, and the log for errors.
Q8Does a Pre-Processor show up in the results?
No. It produces no result row, so check the sent request, the variable values, and the log file.
Q9Is a Pre-Processor thread safe?
Variables are private to each thread, so they are safe. Shared files, properties, and scripts that share data need care.
Q10Where should I do work that only needs to happen once?
In a Setup Thread Group or at start-up, not in a Pre-Processor, because a Pre-Processor repeats for every request in scope.
Q11Can a Pre-Processor use a value captured earlier?
Yes. An extractor in an earlier step stores the value in a variable, and a later Pre-Processor or sampler can read it.
Q12How do I stop a request that might hang?
Use the Sample Timeout element, which interrupts the sampler after the time you choose, where the sampler supports interruption.
Q13Does a Pre-Processor slow down the test?
It uses processor time on the generator. Small elements are almost free, while heavy scripts, database calls, and wide scopes can add up.
Q14How do data files behave in distributed tests?
Each worker reads its own copy, so split the data across workers to avoid several machines using the same rows.

SSummary and Key Takeaways

Pre-Processors are the dressing room of JMeter requests. They run just before a sampler, after Config Elements and before Timers, and they turn identical robot requests into realistic traffic by giving each virtual user its own values, tokens, and limits. Used well, they are small, narrow, named, and verified. Used badly, they hide failures, waste processor time, and confuse the next reader. If you remember one idea, let it be this: prepare only what realism requires, as close to the request as possible, and always check that the preparation really worked.

Key Takeaways

  • A Pre-Processor prepares a request just before it is sent. It runs after Config Elements and before Timers, the sampler, and Post-Processors.
  • Scope sets how often it runs. It runs before every sampler under its parent, in every iteration, so narrow scope saves work.
  • Pick the simplest element. Use Config Elements, tables, and functions first, and a short JSR223 script only when nothing simpler fits.
  • Use variables for per-user data. Variables are private to a thread, while properties are shared by everyone and need care.
  • Preparation is invisible in the results. Check the sent request, add assertions, and read the log after every run.
  • Plan for scale. Keep preparation cheap, split data across workers in distributed tests, and watch the generator’s memory and processor use.
  • Protect the data and the plan. Use test accounts, keep secrets out of shared files, and review scripts before running them.