JMeter Timers: Pacing and Think Time Done Right
The difference between JMeter's Constant Timer, Uniform Random Timer, and Constant Throughput Timer, and which one actually controls throughput.
Timers control the gaps between requests, and picking the wrong one is a common reason a JMeter test’s actual throughput doesn’t match what was intended.
Constant Timer
Adds a fixed delay before each sampler it applies to. Simple, but unrealistic — real users don’t pause for exactly 3.000 seconds every time. Useful mainly for simple pacing where variability doesn’t matter much, or as a placeholder during early scripting.
Uniform Random Timer / Gaussian Random Timer
Adds a randomized delay (uniform or normal distribution) around a base value, which more realistically models human think time variability than a constant delay. Good default choice for simulating “user reading a page before clicking” behavior.
Constant Throughput Timer — the one people misunderstand
This timer tries to enforce a target throughput (samples/minute) by dynamically adjusting delay, rather than just adding a fixed pause. Critically, its throughput target can be scoped per-thread or shared across all threads (“Calculate Throughput based on” setting) — using the wrong scope here is the single most common cause of “I set throughput to X but I’m getting Y.” If you want a total test throughput target shared across all virtual users, you must select the option that divides the target across all active threads, not per-thread.
Constant Throughput Timer can only slow down requests to hit a target — it cannot make threads go faster than their natural request rate allows. If your target throughput requires more concurrency than your Thread Group provides, this timer will silently under-deliver rather than error.
Precise Throughput Timer (newer alternative)
A more statistically rigorous version of Constant Throughput Timer, supporting a Poisson-distributed arrival pattern (closer to how real, independent users actually arrive) rather than the older timer’s more mechanical pacing. Prefer this when modeling open-system, arrival-rate-based traffic (see this site’s article on closed vs. open system load modeling).
Where timers go in the test plan
A timer applies to whatever samplers share its scope (its position in the tree). Place it as a sibling before the sampler(s) it should delay, at the Thread Group level if it should apply to everything in that group, or nested inside a Transaction Controller for narrower scope.
Pacing calculation worth doing by hand first
Before reaching for a timer, calculate the pacing math directly: cycle_time = 3600 / (target_throughput / virtual_users), then think_time = cycle_time − response_time. This site’s pacing calculator does this instantly — use it to sanity-check whatever timer value you’re about to configure, since a misconfigured timer scope will give you a number that looks plausible but doesn’t match the math.
Takeaway: Constant Throughput Timer’s scope setting (per-thread vs. all-threads) is the detail that determines whether your configured target throughput is even achievable — check it before trusting any number derived from a timer-paced test.
Comments are powered by Giscus (GitHub Discussions). Enable them by
configuring GISCUS in src/consts.ts — see
giscus.app.