Skip to main content

Which is the Execution Order of Elements in Apache JMeter?

Which is the Execution Order of Elements in Apache JMeter?

Key takeaways

  • For every sampler, JMeter runs the elements in scope in this order: configuration elements, pre-processors, timers, the sampler, post-processors, assertions, listeners.
  • Samplers and logic controllers follow the order of the tree. Everything else runs by type and by scope, and only in tree order within the same type.
  • Scope comes from the parent: an element applies to every sampler under its parent, so a timer or extractor placed high in the tree runs for every request below it.

The JMeter execution order, as the Apache JMeter user manual defines it, is: configuration elements, pre-processors, timers, the sampler, post-processors, assertions and listeners. The last three run only when the sampler produced a result. JMeter does not run a test plan top to bottom. Samplers and logic controllers follow the tree order, while every other element runs according to its type and its scope, which is why moving a timer or an extractor up or down in the tree often changes nothing.

Knowing the order, and the scoping rules behind it, explains most of the surprising behaviour in a test plan: a pause that lands in the wrong place, a variable that is empty, an extractor that runs for requests you never meant it to. For the bigger picture of threads, samplers and results, see how Apache JMeter works.

What is the execution order of elements in JMeter?

For each sampler it is about to run, JMeter collects every element in that sampler’s scope and processes them in a fixed sequence by type. The order below is the one in section 3.9 of the JMeter user manual (JMeter 5.6.3). Timers, assertions, pre- and post-processors are processed only if there is a sampler they apply to; an element with no sampler in its scope never runs.

  1. Configuration elements
  2. Pre-Processors
  3. Timers
  4. Sampler
  5. Post-Processors (unless the sample result is null)
  6. Assertions (unless the sample result is null)
  7. Listeners (unless the sample result is null)

Two rules sit on top of that list. Logic controllers and samplers are processed in the order in which they appear in the tree. Other elements are processed by scope and type, and within one type, in the order in which they appear in the tree. So two timers in the same scope run in tree order, but a timer placed below a sampler still runs before it. Which samplers run at all, and how many times, is up to the logic controllers above them; our guide to JMeter logic controllers counts the samples most of them produced in a real run.

A worked example from the JMeter manual

The manual illustrates the order with this test plan:

Controller
  Post-Processor 1
  Sampler 1
  Sampler 2
  Timer 1
  Assertion 1
  Pre-Processor 1
  Timer 2
  Post-Processor 2

All six non-sampler elements are children of the controller, so all of them apply to both samplers. JMeter runs them like this:

Pre-Processor 1
Timer 1
Timer 2
Sampler 1
Post-Processor 1
Post-Processor 2
Assertion 1
Pre-Processor 1
Timer 1
Timer 2
Sampler 2
Post-Processor 1
Post-Processor 2
Assertion 1

Three things to notice. Post-Processor 1 sits above both samplers in the tree and still runs after each of them. The whole set repeats for Sampler 2, because each element applies to every sampler in its scope. And the two timers add up: JMeter waits for the sum of all timers in scope before each sampler.

JMeter scoping rules: which samplers does an element apply to?

The manual splits test elements into two kinds. Samplers and controllers are ordered: they run in the sequence you see. Listeners, config elements, pre-processors, post-processors, assertions and timers are hierarchical: what matters is their parent, not their position.

A hierarchical element applies to its parent and everything under it:

  • Child of a sampler: it applies to that one sampler only. This is how you attach an assertion or an extractor to a single request.
  • Child of a controller: it applies to every sampler under that controller, including nested ones.
  • Child of the Thread Group or Test Plan: it applies to every sampler in the thread group or the whole plan.

The manual’s way to picture it: imagine each request travelling up the tree to its parent, then to its parent’s parent, collecting every configuration element on the way. Whatever it collects is what runs around that request.

Configuration elements have a few extra rules:

  • A config element inside a branch takes precedence over the same element in a parent branch. Two HTTP Request Defaults (one in a Loop Controller, one in the Thread Group) means samplers inside the loop use the inner one; the defaults are merged into the values the sampler sees.
  • HTTP Header Managers are merged too: entries from every Header Manager in scope form the header list, and an entry with the same header name replaces the earlier one. That lets you set default headers at the top and override one header for a single request.
  • Cookie Managers are not merged. If more than one Cookie Manager is in a sampler’s scope, there is no way to choose which one JMeter uses, and cookies stored in one are not visible to the other. Use one per thread group.
  • User Defined Variables are processed at the start of the test, wherever you put them. The manual suggests placing them at the top of the Thread Group so the plan reads the way it runs. The User Defined Variables guide covers them in detail.
  • The CSV Data Set Config reads its next line at the start of each iteration, so each pass of the thread loop gets fresh values. More in how to use the CSV Data Set Config.

Listeners follow the same idea: a listener collects data only from elements at or below its level, so a listener inside a controller sees only that controller’s samples.

Common surprises the execution order explains

A timer pauses before the request, not after it. Timers run before each sampler in their scope. To pause after a specific request, add the timer to the next sampler, or use a Flow Control Action sampler with a timer as its child. A timer at Thread Group level delays every single sampler, and two timers there add their delays together.

An extractor runs for every request below its parent. A Regular Expression or JSON Extractor placed under the Thread Group runs after every sampler, and each run can overwrite the variable with an empty or default value. Put extractors as children of the sampler whose response they read.

Post-processors run before assertions. An extractor attached to a request runs even if an assertion on that same request will fail a moment later. That also means an assertion can check a variable the extractor just set.

A pre-processor at the top runs before every request. A JSR223 PreProcessor directly under the Thread Group runs before each sampler, not once per thread. For a value you need once per thread, use a Once Only Controller or set it in a setUp Thread Group.

Timers do not inflate response times, by default. A sampler’s elapsed time does not include its timers. A Transaction Controller also excludes timers and pre/post-processor time from its generated sample unless you tick “Include duration of timer and pre-post processors in generated sample”.

A failed result does not stop the sequence early, a missing one does. Post-processors, assertions and listeners are skipped only when the sample result is null, for example when a sampler did not run at all. A request that returned a 500 still has a result, so its extractors, assertions and listeners all run.

JMeter elements in each category

These are the built-in elements in each group in JMeter 5.6.3, as listed in the component reference. Plugins add more.

Configuration elements: CSV Data Set Config, FTP Request Defaults, DNS Cache Manager, HTTP Authorization Manager, HTTP Cache Manager, HTTP Cookie Manager, HTTP Request Defaults, HTTP Header Manager, Java Request Defaults, JDBC Connection Configuration, Keystore Configuration, Login Config Element, LDAP Request Defaults, LDAP Extended Request Defaults, TCP Sampler Config, User Defined Variables, Random Variable, Counter, Simple Config Element, MongoDB Source Config (deprecated), Bolt Connection Configuration.

Pre-processors: HTML Link Parser, HTTP URL Re-writing Modifier, User Parameters, BeanShell PreProcessor, JSR223 PreProcessor, JDBC PreProcessor, RegEx User Parameters, Sample Timeout.

Timers: Constant Timer, Gaussian Random Timer, Uniform Random Timer, Constant Throughput Timer, Precise Throughput Timer, Synchronizing Timer, BeanShell Timer, JSR223 Timer, Poisson Random Timer.

Samplers: FTP Request, HTTP Request (also used for SOAP and REST web services), JDBC Request, Java Request, LDAP Request, LDAP Extended Request, Access Log Sampler, BeanShell Sampler, JSR223 Sampler, TCP Sampler, JMS Publisher, JMS Subscriber, JMS Point-to-Point, JUnit Request, Mail Reader Sampler, Flow Control Action, SMTP Sampler, OS Process Sampler, MongoDB Script (deprecated), Bolt Request.

Post-processors: Regular Expression Extractor, CSS Selector Extractor, XPath2 Extractor, XPath Extractor, JSON JMESPath Extractor, Result Status Action Handler, BeanShell PostProcessor, JSR223 PostProcessor, JDBC PostProcessor, JSON Extractor, Boundary Extractor.

Assertions: Response Assertion, Duration Assertion, Size Assertion, XML Assertion, BeanShell Assertion, MD5Hex Assertion, HTML Assertion, XPath Assertion, XPath2 Assertion, XML Schema Assertion, JSR223 Assertion, Compare Assertion, SMIME Assertion, JSON Assertion, JSON JMESPath Assertion.

Listeners: Graph Results, Assertion Results, View Results Tree, Aggregate Report, View Results in Table, Simple Data Writer, Aggregate Graph, Response Time Graph, Mailer Visualizer, BeanShell Listener, Summary Report, Save Responses to a file, JSR223 Listener, Generate Summary Results, Comparison Assertion Visualizer, Backend Listener.

When you feed test data in through config elements and pre-processors, the JMeter parameterization guide shows how the pieces fit together.

Run your JMeter test plan in the cloud

Once the plan behaves the way you expect locally, you can upload the .jmx to LoadFocus and run JMeter tests in the cloud from 25 regions, with paid plans scaling up to 20,000 virtual users per test. Thread groups, timers, assertions and JSR223 samplers run as they do on your machine. If you do not have a script yet, the LoadFocus Chrome extension records the HTTP/S traffic of your browser session and generates the .jmx for you, and the free JMeter script validator checks a plan for errors before you run it.

Written by Bogdan Vazzolla.

LoadFocus is a cloud testing platform for websites and APIs. It runs load tests and JMeter or k6 scripts from 25+ cloud locations, keeps the history of your results so you can compare runs and spot performance improvements or regressions, and also monitors APIs and page speed.

Frequently Asked Questions

What is the order of execution in JMeter?

Configuration elements, pre-processors, timers, the sampler, post-processors, assertions and listeners. JMeter applies this sequence to every sampler, using the elements in that sampler’s scope. Post-processors, assertions and listeners are skipped only if the sampler produced no result at all.

Does JMeter run elements top to bottom?

Only samplers and logic controllers. They run in the order they appear in the tree. Every other element runs by type and scope, so a timer placed below a sampler still runs before it. Within the same type, elements run in tree order.

Which elements run first in JMeter?

Configuration elements and pre-processors, before the sampler, wherever they sit inside their scope. User Defined Variables are a special case: JMeter processes them once at the start of the test, wherever they are placed.

Do timers run before or after the sampler in JMeter?

Before. A timer delays every sampler in its scope, and if several timers are in scope, JMeter adds their delays together. To pause after a request, attach the timer to the next sampler or to a Flow Control Action sampler.

What are scoping rules in JMeter?

Scoping rules decide which samplers an element applies to. A timer, assertion, pre-processor, post-processor or config element applies to its parent and every sampler beneath it. As a child of a sampler it applies to that sampler only; under a controller it applies to every sampler in that controller.

Why does this matter?

Because it explains most surprising behaviour with variables and timers. A variable that seems set too early, an extractor that keeps overwriting a value, or a pause landing in the wrong place is usually the execution order or the scope, not a JMeter bug.

Sources

Run this JMX in the cloud, from 25+ regions

Upload your JMeter script to LoadFocus and run it with thousands of virtual users from 25+ cloud locations, with no load generators to manage. Results show p95/p99 response times, throughput and errors per request, and a free tier is included.

JMeter Cloud Load Testing

Free API Load Test

Chris

Head of Content at LoadFocus

Chris leads content and oversees development across the services this blog covers. The guides and tool comparisons here come out of the same decisions that shape what ships.

Weekly tips right in your inbox.

Don’t miss out on the latest testing tips and tricks, tools and news related to software testing.

Already +20,000 members in the list.

The Load Testing Platform with AI That Explains Your Results

Load test websites and APIs from 25 cloud regions, monitor page speed and uptime, and get AI analysis that explains your results in plain English.

Cloud load testing, website speed and API monitoring in one place.

Hi there! Can I share a cool thing I'm working on with you?

A software testing newsletter that sparks joy.

Our goal is to create helpful content for software developers and testers.

If you're not into it, you can unsubscribe instantly.