User Defined Variables in JMeter: Name It Once, Use It Everywhere

User Defined Variables in JMeter: Name It Once, Use It Everywhere

A deep, plain-English guide to the element that gives test values a name, covering how it works inside, why its placement surprises people, how it differs from properties and its sibling elements, and the traps that quietly make every virtual user behave the same way.

Picture a large family kitchen with a whiteboard on the wall. At the top of the board someone has written the Wi-Fi password, the address of the nearest pharmacy and the time dinner is served. Nobody in the house memorises these facts; everybody simply looks at the board. When the pharmacy moves, one person rubs out a line and writes a new one, and the whole family is instantly up to date.

A JMeter test plan needs exactly such a whiteboard. Server names, port numbers, paths, waiting times and many other values appear in dozens of places. If each place holds its own copy, changing the server means hunting through the whole plan. The User Defined Variables element is the whiteboard. This guide explains it from zero knowledge, shows how it works inside, and teaches the rules that decide whether it helps you or quietly misleads you.

1What User Defined Variables Are and Why They Exist

We begin with the problem they solve, because the element only makes sense once the problem is clear.

The copy-and-paste problem

A realistic test plan repeats the same facts again and again. The address of the server appears in every web request. The name of an environment appears in headers and paths. A waiting time may be used in many timers. If each of these is typed directly into each element, the plan becomes brittle. Switching from a development server to a test server means editing dozens of fields, and missing even one produces a test that quietly hits the wrong system.

The solution in one sentence

The User Defined Variables element holds a table of names and values. Anywhere else in the plan, you refer to a value by its name, and JMeter substitutes the real value when the test runs. Change the table once and every reference follows.

What happens without it

Without named values, teams tend to fall into one of two poor habits. Some copy the same address into every request, so every environment change becomes a hunt through the plan. Others keep several nearly identical copies of the whole plan, one per environment, and the copies slowly drift apart until nobody knows which one is correct. Both habits waste time and produce results nobody fully trusts. A single table of named values removes the need for either.

Why it matters for quality

Named values make a plan easier to read, because a request pointed at a name such as the shop address says what it means. They make a plan easier to move between environments. They also make reviews safer, because a colleague can check one table instead of scanning every request.

Simple Analogy

Think of a contacts list on your phone. You do not memorise your friend’s number; you tap the name. When the number changes, you update one entry and every future call goes to the right place. User Defined Variables are the contacts list of your test plan.

One
place to change a shared value
Many
places that can refer to it by name
Start
of the test is when it is evaluated

2Core Concepts You Need First

A handful of terms appear throughout this guide, and learning them now makes everything easier.

Term 1

Variable

A named value that JMeter looks up when a field mentions it. Each virtual user holds its own private set of variables.

Term 2

Property

A named setting shared by the whole test and usually supplied from outside, such as from the command line. Properties are global; variables are private.

Term 3

Config Element

A helper element that supplies settings to other elements. User Defined Variables is a config element.

Term 4

Function

A small built-in calculator written between curly braces, such as one that reads a property, makes a random number or returns the time.

Term 5

Thread

One virtual user. Each thread has its own variable set, so one user’s changes do not affect another.

Term 6

Reference

A dollar sign followed by a name in curly braces. JMeter replaces the whole reference with the value when the field is used.

Term 7

Test Plan

The root of the whole test. It has its own built-in table of user defined variables, which behaves like the separate element.

Term 8

Extractor

An element that captures a value from a response and stores it in a variable at run time, as opposed to a value known in advance.

i
Remember

A user defined variable is a value you know before the test begins. Values that are only discovered during the test, such as a token returned by the server, belong to extractors, not to this element.

3Where It Fits Among the Ways Values Reach a Test

There are many ways to give a value to a JMeter plan, and each suits a different job.

SourceWhen the Value Is KnownTypical Use
User Defined VariablesBefore the test startsConstants such as host, port and paths
Property from command lineWhen the test is launchedEnvironment, user count, duration
CSV Data Set ConfigAs each user iteratesAccounts, search terms, product codes
User Parameters pre-processorPer user, per iterationDifferent values for different users
CounterAt each useIncrementing numbers and unique identifiers
Random VariableAt each useRandom numbers within a range
ExtractorsFrom a response during the runTokens, identifiers, dynamic values
Script elementsWhenever the script runsComputed values and custom logic
flowchart LR
  A[Command line properties] --> V[Variables used in requests]
  B[User Defined Variables] --> V
  C[CSV data file] --> V
  D[Counter and Random elements] --> V
  E[Extractors from responses] --> V
  F[Scripts] --> V
  V --> R[Samplers, timers and assertions]
        
FIG 1 — Many sources feed the same pool of variables that elements read
i
Reading the Picture

All these sources end up as named values that samplers and other elements read in the same way. The skill is choosing the source whose timing matches how the value should behave.

4How It Works Inside

The behaviour looks simple until you see when the values are really worked out.

Evaluated once, at the start

JMeter’s documentation states that every User Defined Variables element in a plan is processed at the start of the test, no matter where it sits in the tree. The values are worked out one time, before the virtual users begin their real work. This is why the element is a good home for constants, and why it is a poor home for anything that is meant to change.

Each thread receives its own copy

When threads start, each one receives its own set of variables, seeded with the values the element produced. From that moment on, a thread may change its own variables, for instance when an extractor stores a token, without affecting any other thread. The starting values are shared in origin but the working copies are private.

Order inside the table

Within one element, rows are processed from top to bottom, so a later row may refer to an earlier one. Across several elements, they are processed in the order they appear in the plan. If the same name is defined twice, the later definition wins. This gives you a simple, predictable way to build a value from smaller parts.

sequenceDiagram
  participant S as JMeter Start-up
  participant U as User Defined Variables
  participant T1 as Thread 1
  participant T2 as Thread 2
  S->>U: Process all elements top to bottom
  U-->>S: Names and evaluated values
  S->>T1: Give private copy
  S->>T2: Give private copy
  T1->>T1: Extractor stores token in own copy
  T2->>T2: Extractor stores different token in own copy
        
FIG 2 — Values are evaluated once, then every thread works on its own copy
Simple Analogy

Imagine a teacher who writes a worksheet once and photocopies it for every student. The worksheet is identical at the start, but each student then writes their own answers on their own copy. User Defined Variables are the original worksheet; thread variables are the individual copies.

!
Common Misconception

Believing that changing a variable inside one thread changes it for everybody. It does not. Variables are private per thread. Only properties are shared across the whole test.

5Defining Variables Step by Step

Creating the element takes a minute, and doing it carefully saves hours later.

1

Add the element

Right-click the test plan or a thread group, choose to add a config element and pick User Defined Variables. Give it a clear name, such as one describing the environment settings it holds.

2

Add a row for each value

Each row has a name and a value. Newer versions also offer a description column, which is an ideal place to record what the value means and where it comes from.

3

Choose clear names

Use short names without spaces, written consistently, such as one style for hosts and another for timings. Names are case-sensitive, so capital letters matter.

4

Fill in the values

Values are text. A number is stored as the characters of that number. A value may also contain references to earlier variables or to functions.

5

Use the names elsewhere

In any field that accepts text, such as a server name, path, header or timer delay, write a reference to the variable instead of the literal value.

6

Test with one user

Run a single user and inspect the resolved requests to confirm every reference was replaced by the value you intended.

A short review before saving

Before you save the plan, read the table once from top to bottom. Check that every name is spelled the way the rest of the plan spells it, that no value has a stray space at either end, that each row refers only to rows above it, and that the description column says what each value is for. This two-minute review catches most of the errors that otherwise cost an hour of confused debugging later.

i
Time Saver

The element offers buttons to add rows from the clipboard and to move rows up and down. When you already have a list of settings in a text file, pasting them in bulk is much faster than typing each row.

6Referencing Variables and the Helpful Functions

A variable is only useful once something refers to it, and a few functions make those references much more powerful.

Basic Reference

Dollar, Braces and Name

Writing a dollar sign, an opening brace, the variable name and a closing brace tells JMeter to insert that variable’s value. If the variable does not exist, the text usually stays as written, which is a useful warning sign.

Function

Read a Property

The property function reads a shared setting and lets you give a default if it is missing. It is the standard way to let the command line override a value in the plan.

Function

Variable by Name

The variable function looks up a variable whose name is itself stored in another variable. It supports tables of settings chosen by a label, such as one set per environment.

Function

Property Alternative

A second property function reads a property too, useful when a default is needed in different contexts. Check the function list in your version.

Helper

Function Helper Dialog

A dialog in the options menu lets you pick a function, fill its arguments and see the exact text to paste, with a button to evaluate it.

Detail

Commas Inside Arguments

Commas separate function arguments, so a comma that belongs to a value must be escaped with a backslash, or the function will see too many arguments.

Where references are allowed

Almost every text field in a plan accepts references: server names, ports, paths, parameter values, headers, timer delays, assertion patterns and more. A few fields that are evaluated before threads exist, notably some thread group settings, are better served by properties, a point covered in detail later.

!
Common Mistake

Mistyping a name by one letter or by case. The reference then does not resolve, and the literal text, dollar sign and all, is sent to the server. Always inspect resolved requests in a one-user run.

7The Test Plan Table Versus the Separate Element

There are two places to define variables, and beginners often wonder whether they differ.

They behave alike

The test plan itself has a built-in table of user defined variables. The separate config element offers the same kind of table. Both are processed at the start, and both supply initial values to every thread. The practical differences are about organisation, not behaviour.

AspectTest Plan TableSeparate Element
Number availableOne per planAs many as you like
Naming and commentsFixed as part of the planCan be named and described
Grouping by purposeAll in one tableSeparate elements for hosts, timings and so on
Reuse across fragmentsPlan level onlyCan be moved with its surrounding elements
Evaluation timeStart of testStart of test

A practical recommendation

Use separate, well-named elements near the top of the plan, grouped by purpose: one for the target system, one for timings, one for feature switches. It keeps each table short and gives each a place for comments. Reserve the plan-level table for a very small plan, or avoid relying on it entirely so that all your settings live in the same kind of place.

i
Consistency Rule

Pick one habit and stick with it. A plan that defines some values in the plan table and others in elements forces every reader to search two places.

8The Scope Surprise: Placement Does Not Localise Them

Most JMeter elements affect only what lies beneath them. This one does not, and that surprises nearly everyone.

The usual rule of scope

Timers, assertions and many config elements apply only to the samplers in their scope, meaning the siblings and children at or below their position. It is natural to assume that a variable table placed inside one thread group applies only to that group.

How this element differs

The documentation is explicit that all User Defined Variables elements in a plan are processed at the start regardless of position. A table inside thread group A therefore defines variables for thread group B as well, because the variables are created before any thread group begins. Position affects only the processing order and the human reading of the plan.

Simple Analogy

Imagine writing a note on one classroom whiteboard, but the school secretary copies every whiteboard’s content onto a single notice shared by every classroom before the day starts. Where you wrote the note no longer matters; everyone will see it.

ANTI-PATTERN-01 Avoid
Problem

Two thread groups each contain a variable table that defines the same name with different values, intending each group to use its own value.

Why It’s Harmful

Because both tables are processed at the start, one definition overrides the other for everyone. Both groups end up using the same value, and the tester believes they are testing two different configurations.

Correct Approach

Give each group distinct variable names, or supply per-group values through an element that is truly scoped, such as a user parameters pre-processor.

!
Practical Consequence

Do not use this element to simulate per-group settings. If different groups need different values, use unique names for each, or choose an element designed for local scope.

9Constants, Not Generators: The Dynamic Function Trap

The single most common mistake with this element is expecting a value to change when it was only ever evaluated once.

What goes wrong

Because values are worked out once at the start, putting a function that produces a different answer each time, such as the current time, a random number or a unique identifier, into a user defined variable freezes the first answer. Every use of the variable afterwards, by every thread and every iteration, receives the same frozen value. The documentation specifically warns that only the result of the first function call is saved.

The consequences are subtle

All virtual users appear to share one timestamp. All orders carry the same reference number. All searches use the same random keyword, so server caches answer instantly. The test runs, the numbers look fine, and nothing signals that the data variety you intended never existed.

You want…Do not useUse instead
A different number each timeA random function in a variable tableRandom Variable element or the function directly in the field
A unique identifier per requestA unique-id function in a variable tableThe function written directly in the request field
Incrementing valuesA counter function in a variable tableCounter config element
The current time at each requestA time function in a variable tableThe time function directly in the field, or a script
Different data per userOne shared variableCSV Data Set Config or User Parameters
ANTI-PATTERN-02 Avoid
Problem

A variable named for the order reference is defined using a unique-identifier function so that each order is unique.

Why It’s Harmful

The identifier is generated once. Every order in the whole test carries the same reference, so the application may reject duplicates or merge them, and the test no longer represents real traffic.

Correct Approach

Place the function directly in the request field so it is evaluated each time the request is built, or use a counter or script that runs per use.

“A user defined variable is a constant wearing a name tag.”

10Letting the Command Line Override: Variables Plus Properties

The most valuable pattern in practice joins this element to properties, so that one plan serves many environments.

The idea

Instead of typing a literal value into the table, write the property function with a default. The variable then takes the property’s value when one is supplied from the outside, and falls back to the default otherwise. A plan opened in the graphical interface just works with its defaults, while the command line supplies different values for different runs without anyone editing the plan.

1

Pick the values that vary

Server name, port, protocol, number of users, duration and think time are typical candidates.

2

Create a variable for each

In the table, define the variable using the property function with a safe default for local debugging.

3

Refer to the variable everywhere

Requests, timers and defaults use the variable name, never the literal value.

4

Supply properties at launch

The command line, or a property file named there, sets the real values for each environment.

5

Record what was used

Save the property values with the results so any run can be reproduced exactly.

Why the default matters so much

The default is not a throwaway detail. It is what runs whenever someone opens the plan and presses start without supplying anything, which happens constantly during development and review. A good default is safe, small and local: a development address, a handful of users and a short duration. A bad default is a trap waiting for a tired colleague. Treat the choice of default as part of the design, and write down what each default represents.

flowchart LR
  A[Command line property] --> B{Property supplied?}
  B -- Yes --> C[Variable takes supplied value]
  B -- No --> D[Variable takes default]
  C --> E[Requests use the variable]
  D --> E
        
FIG 3 — The property function with a default decides each variable’s starting value
i
Debugging Advantage

Because defaults work in the graphical interface, a colleague can open and debug your plan with no extra setup, and the same plan runs headless in the pipeline with overrides.

11Private Per Thread: What Variables Can and Cannot Share

Understanding the privacy of variables explains many puzzling results.

Private by design

Because each thread works on its own copy, a token captured by one user stays with that user. This is exactly what you want for personal values such as session identifiers, and it is why thousands of users can run the same plan without stepping on each other.

Sharing needs a different tool

Sometimes a value found by one thread must reach others, for example an administrator token fetched once for the entire test. Variables cannot do this. Properties are global and can carry such a value, usually written by a script in a setup thread group. Choose carefully, because writing personal data into a shared property makes every user overwrite everyone else.

Use Variables For

Personal Values

Tokens, identifiers and results that belong to one virtual user.

Use Properties For

Shared Settings

Environment names, sizes and values that every thread must see identically.

Use Setup Groups For

Shared Preparation

One-time work that produces values the whole test relies on.

Use Files For

Per-User Data

Lists of accounts or inputs where each user needs a different row.

!
Common Mistake

Storing a per-user token in a shared property because “it worked with one thread”. With many threads, users overwrite each other and requests are sent with someone else’s session.

12Order, Earlier References and Name Collisions

Because values are built in sequence, order becomes a design tool, and also a source of confusing overrides.

Building values from parts

A row may refer to any row above it, in the same table or in an earlier element. This lets you assemble a long value from small, meaningful pieces. A protocol, a host and a port can each be defined once, and a base address built from them in a following row. Later requests then refer to the base address alone. If the host ever changes, one row changes and the base address follows automatically.

What happens when names collide

If two rows define the same name, the later one wins. That is convenient when you intend it, such as a plan-wide default overridden by a more specific definition, but harmful when it happens by accident. A copy-and-pasted table that reuses a name from another table silently replaces the earlier value.

Collisions with run-time sources

Names can also collide with variables created while the test runs. An extractor that stores a value under the same name as a defined constant replaces the constant for that thread from that moment. A data-file element that uses the same name does likewise. Sometimes this is the point, as when a default is replaced by a real value, but unintended collisions are a classic source of mysterious behaviour.

1

Define the building blocks first

Protocol, host and port appear at the top of the table.

2

Compose derived values below

The base address is assembled from the earlier rows.

3

Use only the derived values in requests

Requests refer to the base address, so the building blocks remain an internal detail.

4

Check for duplicates

Search the plan for repeated names before running, especially after combining plans.

!
Common Mistake

Referring to a variable defined in a row below the one using it. Rows are processed top to bottom, so the later row does not exist yet and the reference stays unresolved.

13Sibling Elements: When Another Tool Fits Better

This element is perfect for constants and wrong for almost everything else, so it helps to know its neighbours.

User Parameters pre-processor

Defines values that differ per user and are refreshed on each iteration. Unlike the table, it is genuinely scoped and runs when the thread reaches it, so it suits situations where each user needs a different value and the lists are short.

CSV Data Set Config

Reads rows from a file and assigns each thread a different row. It is the natural choice for accounts, search terms, product codes and other data that must vary across users and iterations at larger volumes.

Counter

Produces an incrementing number at each use, either shared by all users or private to each. It is the right tool for sequence numbers and unique values that simply must not repeat.

Random Variable

Produces a random number within a range at each use, with optional formatting. It suits varied choices such as picking one product from a numbered range.

Extractors

Capture values from responses at run time, such as tokens and identifiers. They are the only way to use values the server decides, so they complement the table rather than compete with it.

Script elements

Compute values with real programming logic, set variables for the thread and even share data through properties. Powerful, but heavier to read and maintain, so use them when simpler elements cannot express the need.

i
Division of Labour

Think of the table as the plan’s constants, data files as its supply of people and things, counters and randoms as its dice, extractors as its listening ears and scripts as its brain.

14Choosing the Right Source for a Value

A short decision table turns the menu of options into a confident choice.

The Value…ChooseReason
Is the same for every user and never changesUser Defined VariablesSimple, readable constants
Changes between environments or runsVariable defined with a property and defaultCommand line can override it
Differs per user and comes from a listCSV Data Set ConfigScales to many users and rows
Must be unique and increasingCounterEvaluated at each use
Must be random within a rangeRandom VariableEvaluated at each use
Is chosen by the server in a responseExtractorCaptured at run time
Must be shared by every thread, computed onceProperty set in a setup groupGlobal and written once
Needs real calculationScript elementFull programming logic

A worked example of choosing

Suppose you need five different pieces of information in one plan: the shop address, a customer account, a unique order number, a delivery slot chosen by the server and the duration of the test. The shop address is a constant, so it belongs in the table, ideally read from a property. The customer account differs per user, so it comes from a data file. The order number must be unique each time, so a counter supplies it. The delivery slot is decided by the server, so an extractor captures it from a response. The duration shapes the whole test, so a property feeds the thread group. Five needs, five different sources, and each one is the natural fit.

Three questions to ask

First, when is the value known: before the test, at launch, or only during the run? Second, who needs it: every user alike, or each user differently? Third, should it change between uses, or stay put? The answers almost always point to exactly one element, and asking them every time prevents the dynamic-function trap described earlier.

“Ask when the value is known and who it belongs to, and the element chooses itself.”

15Environment Configuration Patterns

Most teams use this element mainly to make one plan run against many environments.

The single-table pattern

A small table at the top of the plan defines protocol, host, port and base path, each reading from a property with a development default. The command line or a property file supplies the real values for test, staging and other environments. It is simple, clear and good enough for most projects.

The labelled-environment pattern

For plans that must switch between several complete sets of settings, define each environment’s values under names that include the environment label, then pick the active set using the variable function with a label supplied as a property. One launch property chooses the environment, and every setting follows.

flowchart TD
  A[Launch with environment label] --> B[Variable selects named settings]
  B --> C[Development values]
  B --> D[Test values]
  B --> E[Staging values]
  C --> F[Requests use chosen values]
  D --> F
  E --> F
        
FIG 4 — One label picks a whole set of environment settings

Documenting each environment

Whichever pattern you choose, keep a short written record of what each environment is: its purpose, who owns it, how closely it resembles production and what data it holds. Results from a small, weak environment must never be compared directly with results from a large, production-like one. Writing the environment’s character next to its settings stops people from drawing the wrong conclusion months later.

The property-file pattern

Keep one property file per environment in version control and name the file on the command line. The plan reads properties as before, and switching environment means pointing at a different file. Review of environment changes happens through ordinary code review.

i
Safety Tip

Make the default environment a harmless one, such as a local or development system, so that a launch with forgotten properties cannot accidentally hit a production system.

!
Common Mistake

Leaving a production address as the default value in the table. A colleague who opens the plan and presses start sends a test straight at a live system.

16Thread Group Settings and Why Properties Fit Better

Users naturally want to control the number of users and the duration through variables, but timing makes that awkward.

The timing problem

Thread group settings, such as the number of threads, the ramp-up time and the duration, are read when the group itself is being set up. Variables, in contrast, live inside threads and are created as threads begin. The group’s own configuration therefore comes before the thing that would supply the variable, which makes variables an unreliable source for these particular fields.

The reliable alternative

The property function is evaluated without needing a thread, so it works well in these fields. A thread count field can read a property with a default, and the same plan runs with ten users in the graphical interface and with a thousand from the command line. This is the standard, dependable pattern.

Field

Number of Threads

Read from a property with a small default for debugging.

Field

Ramp-Up Period

Read from a property so tests can use gentle or aggressive arrival patterns.

Field

Loop Count or Duration

Read from a property so a smoke run is short and a soak run is long.

Field

Timer Delays

Delays run inside threads, so a variable works well here, including a variable built from a property.

i
Rule of Thumb

Use properties for anything about the shape of the whole test and variables for anything used inside a running user’s steps.

17Naming Conventions and Organisation

A plan with fifty undocumented variables is a puzzle. A few habits turn it into a readable map.

Habit 1

Descriptive Names

Prefer a name that says what the value means, such as the shop host, over a vague name like value one.

Habit 2

Consistent Style

Choose one style for names and keep to it. Names are case-sensitive, so mixed styles invite mistakes.

Habit 3

Group by Purpose

Use separate elements for target settings, timings and feature switches, each named clearly.

Habit 4

Prefixes for Origin

Mark where a value comes from, for instance with a prefix for constants and another for values captured at run time, so collisions are easy to spot.

Habit 5

Descriptions

Use the description column for units, allowed values and owners of the setting.

Habit 6

No Spaces or Odd Characters

Keep names simple so they are easy to type and cannot be confused with function syntax.

Simple Analogy

Good variable names are like labels on kitchen jars. A jar labelled “sugar” is used correctly by anyone, while an unlabelled white jar causes a salty cup of tea. Labels cost seconds and save embarrassment.

18Everything Is Text: Numbers, Flags and Calculations

User defined variables have no types, which affects how you use numbers and switches.

Text in, text out

Every value in the table is text. A number is the characters of that number, and a switch such as true or false is the word. This is fine wherever a field simply expects text, and also in numeric fields, where JMeter converts the text to a number when it uses it. Problems appear when you try to calculate with them, because there is no arithmetic inside the table.

Calculating when you need to

JMeter provides functions for simple arithmetic, such as adding numbers or evaluating an expression, and script elements for anything more elaborate. Remember that a calculation inside the table is also evaluated only once. If the calculation should use values that change during the run, perform it in an element that runs at that time.

NeedApproachCaution
Use a number in a timer or loopStore the digits as textMake sure no stray spaces are included
Switch features on or offStore the word true or falseConditions compare text exactly, so spelling matters
Add or multiply valuesUse an arithmetic function or scriptTable values are fixed at start
Build text from piecesRefer to several variables in one valuePieces must be defined earlier in order
Convert unitsCompute once at start or in a scriptRecord the unit in the description
!
Common Mistake

Accidental spaces at the beginning or end of a value. A host name with a trailing space, or a number with a leading space, causes odd errors that are very hard to see in the table.

19Debugging Variables

When a value is wrong, the quickest fix starts with seeing exactly what JMeter thinks it is.

1

Run one user

Use a single thread and a couple of iterations so the output is small and readable.

2

Look at the resolved request

The results viewer shows the final address, headers and body after substitution. Any leftover dollar sign and braces means a reference did not resolve.

3

Add a debug sampler

It records the current variables and properties as its output, so you can read every name and value in one place. Disable it before real load.

4

Use the function helper

Evaluate a function expression on its own to confirm it returns what you expect before pasting it into the plan.

5

Check the log

JMeter’s own log reports unresolved functions and errors, and is the best place to see why a function failed to evaluate.

6

Test with two or more users

Confirm that per-user values really differ and that shared values really match.

i
Symptom Guide

Literal dollar-sign text in a request means a name mismatch. Identical “random” values across users mean a frozen function in the table. A value that changed unexpectedly means a name collision with an extractor or data file.

20Variables in Labels and Reports

Names are resolved wherever they appear, including in the labels of requests, with consequences for your reports.

Labels are text too

A sampler’s name accepts references like any other field. That can be handy, for example to include the environment label in the name, but it can also explode the number of distinct labels in a report. If a name includes a value that differs for every request, such as a unique identifier or a timestamp, each request gets its own row in the statistics, and the report becomes unreadable and heavy.

Keep labels stable

Reports group results by label, so labels should describe the kind of request, not the individual instance. Use stable, descriptive names such as the business action. If you need to see parameters, record them in a separate field or in saved response data for failures, rather than in the name.

Stable
labels group results into readable rows
Unique
labels create a row per request
Heavy
reports result from thousands of labels
!
Common Mistake

Putting a per-user or per-request value, such as an account name, into every sampler label so results can be traced. The report fills with thousands of single-sample rows, and the percentiles for each row mean nothing.

21Behaviour in Distributed Tests

When several machines generate load, properties and variables need extra attention.

The plan travels, properties may not

The controller sends the test plan to each worker, so the variable table and its references arrive intact. But properties supplied on the controller’s command line as local settings are not automatically known to workers. A variable defined from a property would then fall back to its default on the workers, with no error, and different machines could test different configurations without anyone noticing.

Global properties solve this

JMeter offers a way to define global properties that are sent to the workers when the test starts. Use it for every value that must match across machines, or place identical property files on each worker. Always confirm, with a short run, that every worker used the same resolved values.

flowchart LR
  C[Controller] -->|plan with variable table| W1[Worker 1]
  C -->|plan with variable table| W2[Worker 2]
  C -->|global properties| W1
  C -->|global properties| W2
  W1 --> R1[Resolved values on worker 1]
  W2 --> R2[Resolved values on worker 2]
  R1 --> M[Values must match]
  R2 --> M
        
FIG 5 — Plans and global properties both travel to workers; local properties do not
!
Common Mistake

Supplying the target server as a local property on the controller only. Workers silently use the default in the plan, which might be a different server entirely.

22GUI Mode Versus Command-Line Mode

The element behaves identically in both modes, but your way of working should differ.

Same behaviour, different purpose

Evaluation happens inside the engine, so variables resolve identically whether the plan runs in the graphical interface or from the command line. Use the interface to define, name and debug variables with one or a few users. Use the command line to run real load with properties supplying the values for each environment.

Edits during a run do not take effect

Because values are processed at the start, changing a table while a test is running does not alter the running threads. Stop the test, edit, and start again. This matters most in the interface, where it is tempting to adjust a value in the middle of a run and expect an immediate effect.

ActivityBest ModeReason
Defining and naming variablesGUITable editing, clipboard paste and ordering are easy
Checking resolved requestsGUI with one userViewer shows the final text after substitution
Running with environment overridesCommand lineProperties supplied at launch, reproducible
Large or long runsCommand lineLower overhead and automation
Recording values usedCommand line with saved propertiesEvery run can be reproduced exactly

23Security Considerations

A table of named values is convenient, and convenience tempts people to store things that should never sit in a plan file.

Plans are plain text

A saved plan is a readable file. Anything typed into the variable table, including passwords and keys, is stored there in plain sight and travels with the file into version control, email and shared folders.

Supply secrets at run time

Read credentials from properties provided by the pipeline’s secret store at launch, and keep the default in the plan empty or harmless. That way the plan can be shared freely without exposing anything.

Beware of defaults that point at real systems

A default host that names a production system turns an accidental press of the start button into an attack on a live service. Default to a safe, isolated environment.

Results can echo variables

Resolved requests saved in results files contain the values substituted in. A token or password placed in a variable may therefore appear in saved results and screenshots.

Property files need protection too

Moving secrets from the plan to a property file only moves the problem. Keep such files out of shared repositories, or use the secret store’s own injection mechanism.

Least privilege for test accounts

Whatever credentials do reach the plan should belong to dedicated test accounts with limited permissions, never to personal or administrator accounts.

!
Common Mistake

Committing a plan with a real password typed into the table because “it is only for the test system”. Test systems are often reachable from places that surprise you, and committed secrets stay in history for ever.

24Design Patterns That Work

These patterns appear again and again in tidy, trustworthy plans.

Pattern

Config at the Top

All named constants live in a few clearly named elements at the very top of the plan, so readers find them at once.

Pattern

Property With Safe Default

Every environment-dependent value reads a property, with a harmless default that works for local debugging.

Pattern

Derived Base Address

Protocol, host and port are separate rows, combined into one base address that requests use.

Pattern

Request Defaults Consume Variables

A defaults element for web requests reads the variables once, so individual requests need no address at all.

Pattern

Separate Constants From Per-User Data

Constants go in the table; accounts and inputs go in data files; run-time values come from extractors.

Pattern

Recorded Settings

The values used for every run are saved with the results, so any run can be reproduced exactly.

Simple Analogy

A good plan is like a well-organised cockpit. The settings are on one panel at the front, clearly labelled, and every instrument reads from that panel. A pilot never searches the cabin for a stray switch.

25More Anti-Patterns to Avoid

Besides the scope surprise and the frozen function, these mistakes look harmless and quietly spoil results.

ANTI-PATTERN-03 Avoid
Problem

Thread counts, ramp-up and durations are controlled through variables from the table.

Why It’s Harmful

Thread group settings are read before threads and their variables exist, so the fields may not resolve as expected, and the test runs with the wrong shape without any error.

Correct Approach

Read these settings from properties using the property function with a default.

ANTI-PATTERN-04 Avoid
Problem

A per-user value, such as a token, is stored in the variable table or in a shared property to make it available to everyone.

Why It’s Harmful

All users send the same token, or overwrite each other’s, so the server sees one identity and the test no longer represents independent users.

Correct Approach

Capture personal values with extractors into private thread variables, and use files or user parameters for per-user inputs.

ANTI-PATTERN-05 Avoid
Problem

The same names are defined in several tables and in extractors and data files, with no convention to tell them apart.

Why It’s Harmful

Later definitions silently override earlier ones. Values change unexpectedly between iterations and nobody can say which element is responsible.

Correct Approach

Adopt a naming convention that shows origin, search for duplicates before every run and keep each name defined in exactly one place.

ANTI-PATTERN-06 Avoid
Problem

Environment addresses are typed directly into dozens of requests, and the table is used only for a few timings.

Why It’s Harmful

Switching environment means editing every request, and a missed edit sends traffic to the wrong system.

Correct Approach

Define the address once as a variable, read it through a request defaults element, and have requests contain only the path.

ANTI-PATTERN-07 Avoid
Problem

A tester edits the variable table while a test is running and expects the change to apply immediately.

Why It’s Harmful

The values were fixed at the start, so the change has no effect on the running test, yet the tester interprets later results as if it did.

Correct Approach

Stop the test, make the change and start again, recording the new settings with the new run.

26Advantages, Disadvantages and Trade-offs

An honest look at benefits and costs shows when the element is the right answer.

Advantages

  • Very simple to learn and to read in the plan
  • One place to change a value used in many places
  • Makes plans portable across environments with properties
  • Supports building values from smaller named parts
  • Needs no scripting and no plugins
  • Behaves identically in graphical and command-line modes

Disadvantages / Trade-offs

  • Evaluated once, so it cannot produce changing values
  • Placement does not limit scope, which surprises newcomers
  • Plain-text storage tempts people to put secrets in plans
  • No types or arithmetic; everything is text
  • Name collisions with other sources override silently
  • Unsuitable for some thread group fields
i
Balance

The element is excellent for one simple job: giving names to constants. When you need variety, sharing, or computation, move to the element designed for that, rather than stretching this one.

27Best Practices Checklist

A short order of operations avoids the stumbles described in this guide.

1

List what changes between runs

Environments, sizes, timings and switches become named variables or properties.

2

Define constants once

Put them in clearly named elements at the top of the plan and refer to them by name everywhere.

3

Use properties with safe defaults

Let the command line override environment settings, and default to a harmless system.

4

Keep changing values elsewhere

Use data files, counters, random elements, extractors and scripts for anything that varies.

5

Keep secrets out of the plan

Inject credentials at run time and never commit them.

6

Prove, then scale, then record

Check resolved requests with one user, run at scale from the command line and save the values used with the results.

!
Common Mistake

Trusting that a plan “just works” because it ran without errors. Always inspect resolved requests, since an unresolved reference sent as literal text often produces a valid-looking, but meaningless, request.

28Uses Beyond Web Requests

Named values help every kind of sampler, not only web ones.

Database tests

Connection addresses, pool names, driver class names and query timeouts are ideal constants. Switching from a test database to a staging copy then means changing one value.

Messaging tests

Broker addresses, connection factory names and destination names are shared by publishers and subscribers. Naming them once keeps both sides pointed at the same place.

Raw socket and file transfer tests

Host names, ports and remote folder paths appear in many samplers. A single table avoids a mismatch between, for instance, an upload and a later download.

Timers and pacing

Think time and pacing values used in many timers can come from one variable, letting you speed up or slow down the whole test by changing one value.

Assertions

Expected text, such as a version string or a page title, can be a variable so the same plan checks different environments or releases.

i
Consistency Benefit

When all samplers draw on the same table, the whole plan stays internally consistent: a change to the environment reaches web, database and messaging steps at the same moment.

29Real-World Scenarios

Stories show how the element helps, and how it can mislead, in everyday projects.

The pipeline that hit the wrong server

A team ran a nightly test from a build server and kept finding it had tested the development system. The environment property was supplied only on the controller of a distributed run, so workers used the default. Switching to global properties fixed the mismatch.

Every order had the same number

A tester generated order references with a unique-identifier function inside a variable. Every order in the test carried the same reference and the application rejected duplicates, producing a flood of errors. Moving the function into the request field restored uniqueness.

Two groups, one value

A plan defined a variable with the same name in tables inside two thread groups, expecting different values per group. Both groups used the last definition. The team gave each group distinct names and the confusion disappeared.

The weekend with production defaults

A plan’s default host pointed at a live site. A colleague opened it, pressed start for a quick check and sent a burst of traffic to production. The team changed the default to a local system and made overrides explicit.

One change, whole plan

A company migrated its test environment to new servers. Because every address was defined once and read through request defaults, the migration meant editing a single row, and a smoke test confirmed the whole plan followed.

The report with thousands of rows

An analyst put each account name into the sampler labels for traceability. The report grew thousands of rows with one sample each. Switching to stable labels made the report readable again.

30Frequently Asked Questions

Q1When are user defined variables evaluated?

At the start of the test, for every such element in the plan regardless of its position. Values are then copied into each thread’s private variable set.

Q2Why do all my users get the same random or unique value?

Because a changing function placed in the table is evaluated only once. Put the function directly in the request field, or use a counter, random variable or data file.

Q3Does placing the element inside a thread group limit it to that group?

No. All such elements are processed at the start, so position affects only order and readability, not scope.

Q4What is the difference between a variable and a property?

A variable is private to one thread. A property is global to the whole test. Use properties for settings shared by everyone, and variables for values that belong to a single user.

Q5Can I use variables for the number of threads?

It is unreliable because thread group settings are read before threads and their variables exist. Use the property function with a default instead.

Q6How can the command line override a variable?

Define the variable using the property function with a default, then supply the property at launch. If it is not supplied, the default applies.

Q7What happens if I refer to a variable that does not exist?

The reference usually stays as literal text, and JMeter logs a warning. Inspect resolved requests to catch this.

Q8Can one row use another row’s value?

Yes, if the other row is above it, in the same table or an earlier element. Rows are processed from top to bottom.

Q9Can I change a variable while the test is running?

Editing the table during a run does not affect running threads. Stop, edit and restart. Individual threads can still change their own variables through extractors or scripts.

Q10Do distributed tests share my variables?

The table travels with the plan, but properties set locally on the controller do not reach workers. Use global properties or matching property files on every worker.

Q11Is it safe to store passwords in the table?

No. Plans are plain text. Supply secrets at run time through properties from a secret store and keep plan defaults harmless.

Q12Should I use the test plan table or the separate element?

They behave the same. Separate, named elements are easier to organise and document, so many teams prefer them. Choose one habit and keep to it.

Q13Why do my report rows look strange after using variables in names?

Names that include per-request values create a separate label for every request. Use stable labels that describe the type of request.

Q14How do I see all current variables?

Add a debug sampler and view its output in a results viewer in a one-user run. It lists variables and properties with their current values. Disable it before real load.

31Summary and Key Takeaways

The User Defined Variables element does one job very well: it gives names to values you know before the test begins, so you can change them in one place. Its behaviour is simple but easy to misjudge. Values are worked out once at the start, regardless of position, and then copied into each thread’s private variables. That makes the element perfect for constants and environment settings, especially when joined to properties with safe defaults, and wrong for anything that must vary, such as unique identifiers, random numbers, per-user data or values the server decides. Choose the element whose timing and scope match the value, keep secrets out of plans, make sure properties reach every worker, and inspect resolved requests before trusting any run.

Key Takeaways

  • Evaluated once, at the start — every such element is processed before the test runs, wherever it sits, so values are constants.
  • Position does not limit scope — a table inside one thread group still defines variables for the whole plan; use distinct names for distinct needs.
  • Never put changing functions in the table — random, time and unique-id functions freeze at their first result; use fields, counters, random elements or data files.
  • Pair variables with properties — the property function with a safe default lets the command line override settings without editing the plan.
  • Variables are private, properties are shared — keep personal values in thread variables and shared settings in properties, and use properties for thread group fields.
  • Organise and name deliberately — descriptive, consistent names, separate elements by purpose and no duplicate definitions prevent silent overrides.
  • Protect and verify — keep secrets out of plans, make workers receive the same properties, and inspect resolved requests with one user before scaling up.