JMeter Scheduler: Duration and Startup Delay
A beginner-friendly but production-minded guide to controlling how long a load test runs and when it begins, so your results come from a planned, repeatable window of time instead of a lucky guess.
Imagine you are the manager of a big concert hall. Before the show, you must answer two simple questions. What time do the doors open, and what time does the last song end? If you do not answer them, people arrive whenever they like, the band plays until it is tired, and nobody can plan anything. A performance test has exactly the same two questions: when should the virtual crowd arrive, and how long should it stay?
Apache JMeter answers these questions through a small but powerful feature inside the thread group, called the scheduler. It has two main settings: Duration, which says how long the test group should run, and Startup Delay, which says how long to wait before it starts. These two numbers look tiny on the screen, yet they decide how long a test lasts, how many measurements you collect, whether several groups overlap or follow each other, and whether the report you show your team can be trusted.
This guide teaches both settings from zero. We begin with what the scheduler is, follow a test through its lifecycle, study how JMeter enforces the clock behind the scenes, and work through realistic examples. Then we move to the topics that separate a beginner script from a production-quality load test: choosing sensible values, combining several thread groups, running in pipelines and across many machines, reading the results, avoiding common traps, and keeping long unattended tests safe.
WWhat Is the Scheduler in JMeter?
The scheduler is a small panel in the thread group that gives a test a start time and a length.
JMeter is a free, open-source tool from the Apache Software Foundation that pretends to be many users at the same time so you can see how a system behaves under pressure. In JMeter, the people you pretend to be are called virtual users, and each one is run by a Java thread. A thread group is the element that holds a crowd of these threads and tells them what to do.
Every thread group has settings for the number of threads, the ramp-up period, and the loop count. Under those you will find the scheduler. Depending on your JMeter version, it is shown as a checkbox labelled “Scheduler” or “Specify Thread lifetime”. When you tick it, two extra boxes become available:
Duration (seconds)
How long the thread group is allowed to run, measured in seconds. When this time is used up, the threads stop.
Startup Delay (seconds)
How long the thread group waits, in seconds, before it begins its work after the test has been started.
Think of a school exam. The invigilator announces, “We start in five minutes, and you will have ninety minutes to write.” The five minutes before starting is the startup delay. The ninety minutes is the duration. When the clock runs out, pens down, whether or not everyone has finished their last sentence.
A timer for the whole group, not for one request
It is easy to confuse the scheduler with the timers that add pauses between requests. They are completely different. A timer adds a short pause before a single request, to imitate a person who is thinking. The scheduler controls the lifetime of the whole thread group: when it begins and when it ends. One works in seconds and fractions of seconds between actions; the other works in minutes and hours across a whole test.
Both fields are measured in seconds, not minutes. A thirty-minute test needs the number 1800. Many beginners type 30 and then wonder why the test finished in half a minute.
WWhy Time-Based Control Matters
Counting loops is easy. Counting minutes is what real performance questions need.
By default, a thread group runs until each thread has repeated its steps a fixed number of times. This number is the loop count. A test with one hundred threads and a loop count of ten sends roughly one thousand journeys through the system, then stops. When the system is fast, this happens in seconds. When it is slow, the same test takes much longer. In other words, the length of the test depends on the very thing you are trying to measure.
That is a problem. Real questions about performance are almost always phrased in time: “Can the system handle the expected crowd for thirty minutes?”, “Does memory slowly leak over eight hours?”, “What happens during the first five minutes after a sale starts?” To answer questions like these, you need the test to run for a chosen length of time, whatever the speed of the system. The scheduler provides exactly that.
Counting loops
- Easy to understand and good for quick checks
- Gives a fixed amount of work per user
- Test length changes when the system speed changes
- Hard to guarantee a steady period of measurement
Using the scheduler
- Test length is predictable and easy to plan around
- Natural fit for steady-load, soak, and spike tests
- Total work done depends on how fast the system is
- Needs care with loop count and ramp-up settings
Predictability helps everyone
Time-based tests are easier to schedule with other people. You can tell the operations team, “We will hit the system between ten and ten thirty, and the monitoring dashboards should be watched during that period.” You can plan a pipeline stage that must finish within a limit. You can compare two runs fairly because they ran for the same length of time at the same load. And you can calculate the number of samples you expect to collect, which tells you whether your statistics are strong enough to trust.
Most professional load tests describe the plan as a timeline: a delay, a ramp-up, a steady period, and an end. The scheduler fields are how that timeline is written into the thread group.
TThe Thread Group Timeline
Every scheduled thread group moves through the same stages. Learn the stages once and every setting makes sense.
When you press the start button, the test does not simply explode into action. A scheduled thread group walks through a predictable sequence of stages, and each setting controls one of them.
flowchart LR
S["Test started"] --> D["Startup Delay: group waits"]
D --> R["Ramp-Up: threads join gradually"]
R --> ST["Steady State: all threads working"]
ST --> E["Duration ends: threads stop"]
E --> F["Test finishes or next group continues"]
Startup delay
Nothing is sent to the system. The group simply waits. This is the quiet time before the doors open.
Ramp-up
Threads start one after another, spread evenly across the ramp-up period, so the crowd grows gradually instead of arriving all at once.
Steady state
All threads are running and the load is stable. This is the most valuable stretch for measuring, because the conditions are not changing.
End of duration
The clock runs out. JMeter tells the threads to stop, and the group finishes.
A picture in numbers
Suppose a group has one hundred threads, a startup delay of 60 seconds, a ramp-up of 100 seconds, and a duration of 1800 seconds. For the first minute, nothing happens. Then, over the next hundred seconds, one new virtual user joins every second. After that, all one hundred users work together until the duration is finished. The steady state lasts the rest of the time, which is the bulk of the test.
Picture a swimming pool opening for the day. The attendant unlocks the gate at a fixed time (startup delay). Swimmers trickle in over the first half hour (ramp-up). The pool is comfortably busy for most of the day (steady state). At closing time, the whistle blows and everyone leaves (end of duration).
When you plan a test, draw this timeline on paper first. Write the delay, the ramp-up, the steady period, and the end next to each other. Then turn the lengths into seconds and type them into the fields.
DDuration Explained
Duration is the total length of life you give to a thread group.
The Duration field answers one question: for how many seconds should this group be allowed to run? When the scheduler is active and a duration is set, JMeter calculates an end time from it and tells the threads to stop when that moment arrives.
What the duration includes
The duration includes the ramp-up. It is a single clock that starts when the group begins and covers the time the threads are still joining as well as the time all of them are working. This surprises many beginners. If your duration is 600 seconds and your ramp-up is 300 seconds, then half of your duration is spent while the crowd is still growing, and only the remaining half is true steady state.
| Duration | Ramp-up | Steady period left | Comment |
|---|---|---|---|
| 600 s | 60 s | 540 s | Comfortable. Most of the test is stable. |
| 600 s | 300 s | 300 s | Half the test is spent growing. Acceptable only if you plan for it. |
| 600 s | 600 s | 0 s | The crowd is still growing when the clock ends. No steady period at all. |
| 300 s | 600 s | None | The group stops before the last users even join. Result is a misleading test. |
How a duration is chosen
There is no single correct duration. It depends on the question. A quick sanity check after a code change may run for five minutes. A normal load test often runs for thirty to sixty minutes. A soak test, which looks for slow problems such as memory leaks, may run for many hours. We will return to the choice later in a dedicated chapter, but for now remember that the duration should be long enough to collect many measurements during a stable period.
What happens when the duration is empty
If the scheduler is on and the duration is left blank or zero, JMeter has no end time from this field. The group then relies on the loop count to decide when to stop. If the loop count is also infinite, the test would run until someone stops it by hand. That is a classic cause of tests that never finish, so always check both fields together.
Ticking the scheduler box but leaving the duration empty does not give you a time-limited test. The checkbox only unlocks the fields. You must still type a positive number into Duration.
The duration and finite loops
If you set both a duration and a finite loop count, the group ends as soon as either one is reached first. A group of fifty threads with a loop count of five and a duration of one hour will probably finish in a few minutes, long before the hour, because the threads run out of loops. If your goal is “run for exactly one hour”, set the loop count to infinite so that the duration alone controls the end.
SStartup Delay Explained
Startup delay is a polite pause before a thread group begins its work.
The Startup Delay field says how many seconds a thread group should wait after the test is started before it begins. During the wait, the group does nothing at all and sends no traffic. After the wait, it begins its ramp-up and starts its threads.
Why would anyone wait?
If you only have one thread group, a startup delay is rarely needed. Its real power appears when a test has several groups. By giving each group a different delay, you decide who arrives first, who arrives later, and who overlaps with whom.
Different crowds arrive at different times
Browsers might start at once, while buyers arrive ten minutes later, as they would after a marketing email lands.
Let background traffic settle first
A light group can run alone for a while so caches and connections warm up before a heavier group joins.
Time a surprise on purpose
A delayed group can simulate a sudden event in the middle of normal traffic, such as a sale starting or a batch job kicking off.
Give monitoring time to start
A short delay at the beginning gives your dashboards and server monitors a moment to begin collecting before the first request arrives.
In a relay race, the second runner does not start running when the gun fires. They wait at their spot until the first runner arrives. A startup delay gives a thread group that same patient waiting time, so it starts at the right moment in the race.
Delay is relative, not a clock time
The startup delay is a relative number. It means “wait this many seconds after the group is told to start”, not “start at three o’clock”. This is helpful because the test behaves the same whether you start it at nine in the morning or midnight. It also works well when the same plan is shared by many machines, since each machine counts the delay from its own start moment.
The delay is counted from the moment the test starts, not from the moment the previous group ends. If group A runs for ten minutes and you want group B to start right after, set B’s delay to 600 seconds, not to a small number.
CCombining Duration and Startup Delay
The two settings are partners. Together they place a thread group on the timeline of the whole test.
To know exactly when a group is active, add the startup delay to the duration. A group with a startup delay of 300 seconds and a duration of 1200 seconds begins working after five minutes and finishes twenty minutes after that, so it is active until the 1500-second mark of the test. Remember to confirm this in your own JMeter version by watching a chart of active threads over time during your first run, because small differences between versions do exist.
| Group | Delay | Ramp-up | Duration | Active period |
|---|---|---|---|---|
| Browsers | 0 s | 120 s | 1800 s | From 0 s to about 1800 s |
| Searchers | 300 s | 120 s | 1200 s | From 300 s to about 1500 s |
| Buyers | 600 s | 60 s | 600 s | From 600 s to about 1200 s |
This plan builds the load gradually. Browsers arrive first and form the background. Searchers join five minutes later. Buyers join five minutes after that, when the system is already busy. The test is therefore heaviest in the middle, and it winds down as groups finish at different moments, which is an excellent way to see how the system behaves as load rises and falls.
A rule of thumb for planning
- Decide the length of the whole test from the question you are answering.
- Decide when each crowd should arrive, and write that as its startup delay.
- Decide how long each crowd should stay, and write that as its duration.
- Check that for every group, the ramp-up is clearly shorter than its duration.
- Check that the longest delay plus its duration does not exceed the length of the test you planned.
Keep a small table like the one above in your test notes. When someone asks, “Why did the system slow down at minute twelve?”, you can answer immediately: “Because the buyers joined at minute ten.”
WWorked Examples: Planning Three Schedules by Hand
Numbers become clear when you do the arithmetic yourself. Here are three schedules, worked from start to finish.
Example one: a thirty-minute load test
The team wants about 200 virtual users, a gentle ramp, and a steady period of roughly twenty-one minutes. They choose 200 threads, a ramp-up of 200 seconds, a duration of 1500 seconds, an infinite loop count, and no startup delay. The arrival speed is 200 threads divided by 200 seconds, which is one new user per second. The ramp-up covers the first 200 seconds, so the steady state lasts the remaining 1300 seconds, a little over twenty-one minutes.
Now estimate the work done. If each journey takes about twenty seconds including think time, a thread completes about 65 journeys during the steady state, because 1300 divided by 20 is 65. Multiplied by 200 threads, that is about 13,000 journeys. If a journey contains five requests, the test sends about 65,000 requests in the steady window. That is enough for stable percentiles in most cases.
Example two: a four-hour soak test
A second team wants to look for slow memory growth. They choose 50 threads, a ramp-up of 300 seconds, a duration of 14400 seconds, an infinite loop count, and a startup delay of 120 seconds so monitoring can record a quiet baseline first. The group begins working at the 120-second mark, reaches full strength at 420 seconds, and ends at 14520 seconds. The steady state lasts 14100 seconds, almost four hours. The load is small on purpose; the point is the length, not the weight.
Example three: a spike on top of a background crowd
A third team wants to see how a system copes with a sudden burst. The first group is the background: 100 threads, a ramp-up of 100 seconds, a duration of 1800 seconds, and no delay. The second group is the spike: 400 threads, a ramp-up of 10 seconds, a startup delay of 900 seconds, and a duration of 300 seconds. The spike group arrives at forty new users per second, which is very fast, between the 900-second and 910-second marks. For about 290 seconds the system serves 500 users, then the spike group stops and the system returns to its background load of 100. The team watches how long it takes response times to recover.
| Example | Threads | Delay | Ramp-up | Duration | Ends at |
|---|---|---|---|---|---|
| Load test | 200 | 0 s | 200 s | 1500 s | about 1500 s |
| Soak test | 50 | 120 s | 300 s | 14400 s | about 14520 s |
| Background group | 100 | 0 s | 100 s | 1800 s | about 1800 s |
| Spike group | 400 | 900 s | 10 s | 300 s | about 1200 s |
Do this arithmetic before every test and keep it in your notes. When the real active-threads chart matches your hand calculation, you can trust the test. When it differs, you have found a mistake before it wasted anyone’s time.
UUnder the Hood: How JMeter Enforces the Clock
The scheduler is not magic. It is a few simple rules applied by every thread in the group.
When you start a test, JMeter reads the plan, creates the engine, and starts each thread group. For a scheduled group, JMeter converts your two numbers into actual moments in time. It calculates a start moment by adding the startup delay to the current time. It calculates an end moment by adding the duration to that start moment. Each thread in the group is given these moments, and each thread then checks them as it works.
flowchart TD
A["Test starts"] --> B["Read scheduler settings"]
B --> C["Compute start time from startup delay"]
C --> D["Compute end time from duration"]
D --> E["Each thread waits for its turn during ramp-up"]
E --> F["Thread runs samplers in order"]
F --> G{"End time reached?"}
G -- "No" --> F
G -- "Yes" --> H["Thread stops and reports"]
H --> I["Group ends when all threads stop"]
Threads check the clock between actions
A thread is busy sending a request, waiting for a reply, running extractors, and pausing in timers. JMeter does not slam on the brakes in the middle of ordinary work. Instead, the thread looks at the clock at natural points in its work, such as between samplers. When it sees that the end moment has passed, it stops running its normal steps. A scheduled background task also watches the clock and asks any thread that is still working to stop at the end time.
Because of this, the very end of a scheduled test is a little untidy. A request that is in flight when the clock runs out may be cut short, and a thread that is in the middle of a long think-time pause may take a moment to react. The last few samples of each user can therefore look unusual, with slightly different timings or an error. This is normal, and the proper response is to ignore the tail of the test when you read results.
A restaurant closes at ten. The doorman stops letting new customers in at ten, but the waiters finish the meals already on the tables. A few diners may be rushed, and the kitchen’s last orders look different from the rest of the evening. JMeter’s end of duration behaves the same way.
Why the delay is handled per thread
Each thread knows its own start moment and end moment. This design keeps the engine simple: there is no central referee shouting instructions to every thread. Instead, every thread knows the rules and follows them. This makes it dependable even with thousands of threads, because the only shared fact is the same pair of times.
The data flow and lifecycle
A thread passes through four clear states: waiting, running, stopping, and finished. During the startup delay and its own ramp-up slot, it is waiting. Once its slot arrives, it is running and executes its samplers in order, round after round. When the end moment passes, it moves to stopping, where it finishes or abandons the current work. Finally, it is finished, and the group notes that one more thread has ended. When all threads in the group are finished, the group is complete, and if every group is complete, the whole test ends.
The JMeter log records when threads start and finish. If you are ever unsure whether your schedule did what you expected, the start and finish messages in the log and the active-threads chart in the report are your two best witnesses.
Delaying thread creation
The thread group has a related checkbox that says to delay the creation of threads until they are needed. By default, JMeter creates all of the threads at the start, even though many of them will wait through a long ramp-up. With the option on, each thread is created only when its slot arrives. For very large groups, this saves memory early in the test and lets a long startup delay cost almost nothing while it waits.
LLoop Count versus Duration
Both settings can end a thread. Knowing who wins avoids a whole family of surprises.
A thread can stop for two different reasons: it has finished its loops, or the duration has run out. The thread stops at whichever happens first. Because beginners usually think about only one of them at a time, the combination causes many confusing results.
| Scheduler | Loop count | What happens |
|---|---|---|
| Off | Fixed number, such as 10 | Each thread repeats its steps ten times and stops. Test length depends on system speed. |
| Off | Infinite | The test never ends by itself. It must be stopped by hand. |
| On with duration | Infinite | Threads loop until the duration ends. This is the usual way to get a time-limited test. |
| On with duration | Fixed number | Threads stop at whichever comes first: the loops finishing or the duration ending. |
| On without duration | Fixed number | Duration has no effect, so the loop count alone decides. |
The recommended pairing
For nearly every time-based test, the recommended pairing is scheduler on, a positive duration, and an infinite loop count. With this, the only thing that ends the test is the clock, which is exactly what you want when the goal is “run for this long”. Each thread simply repeats its journey, one iteration after another, until time is up.
A test plan copied from an older quick check may still have a loop count of one. After you add a duration of one hour, each thread runs its journey once, finishes in seconds, and the test ends. The report then shows a tiny number of samples, and nobody understands why the hour never happened.
The cost of looping for a long time
With an infinite loop and a long duration, every thread repeats its journey many times. This has side effects worth planning for. Data files may run out and need to be recycled, otherwise threads may stop early. Created records, such as orders or accounts, may pile up in the system under test. Sessions that last hours may expire. These are not problems with the scheduler, but they are consequences of running for a long time, and the scheduler is what makes a long test easy to start by accident.
Example: the one-hour test that ended in two minutes
A team set the scheduler to 3600 seconds but forgot that their thread group still said “loop count 5”. Each user finished five journeys in about two minutes and the test ended. The fix was to tick the infinite box. The lesson is to read all the fields in the thread group together, not one at a time.
RRamp-Up and the Scheduler Together
Ramp-up decides how fast the crowd arrives. Duration decides how long the whole party lasts. They share the same clock.
The ramp-up period is the number of seconds over which JMeter starts all of the threads. With one hundred threads and a ramp-up of one hundred seconds, one new thread starts about every second. The first thread begins right away and the last thread begins at the end of the ramp-up. The speed of arrival is the number of threads divided by the ramp-up in seconds.
Arrival speed
Threads divided by ramp-up seconds. Fifty threads over twenty-five seconds means two new users every second.
Ramp-up must fit inside duration
If the ramp-up is as long as the duration, there is never a steady state. If it is longer, the last users may never start.
Instant crowd
A ramp-up of zero starts everyone at the same moment. This is a spike test, not a gentle load test, and it creates a storm of new connections.
Never reaches full load
A very long ramp-up spends most of the test below the load you meant to measure.
Choosing a sensible ramp-up
A sensible ramp-up gives the system time to warm its caches and open its connection pools naturally. For a few hundred threads, one to five minutes is common. For thousands, longer is often better. A rule many teams use is to keep the ramp-up under about a quarter of the duration, so most of the test sits in the steady stretch. When you want to see how the system copes with a sudden crowd, deliberately shorten the ramp-up and call it what it is: a spike test.
Filling a bathtub from a tap is better than emptying a bucket in all at once. A steady flow lets you watch the water level and stop in time. Ramp-up is the tap, and a zero ramp-up is the bucket.
Separating warm-up from measurement
The first minutes of a test behave differently from the rest. Caches are cold, connection pools are small, and just-in-time compilers in the server are still deciding what to optimize. Measurements taken during this time are usually slower and noisier. A well-designed schedule treats the delay and ramp-up as warm-up and bases its conclusions on the steady stretch only. When you later read the results, you will cut the first part away, so you must make sure that a steady stretch exists in the first place.
Write your plan as three numbers: warm-up, steady, and cool-down. A plan such as “five minutes warm-up, thirty minutes steady, one minute cool-down” translates directly into delay, ramp-up, and duration settings.
TThread Group Settings That Interact with the Scheduler
The scheduler lives in a crowded panel. Its neighbours change how it behaves.
A thread group has several settings in the same panel as the scheduler. Each of them interacts with duration and startup delay, so it is worth understanding the whole neighbourhood.
Number of threads
The size of the crowd. Together with ramp-up, it sets the speed at which users arrive.
Ramp-up period
The seconds over which the crowd joins. It must fit comfortably inside the duration.
Loop count
How many times each thread repeats its journey. An infinite count lets the duration alone end the test.
Same user on each iteration
Controls whether a thread keeps its state, such as cookies and variables, from one iteration to the next, or starts fresh like a new visitor.
Delay thread creation until needed
Creates each thread only when its ramp-up moment arrives, which saves memory in big groups with long delays.
Action after a sampler error
Decides whether a thread continues, starts a new loop, stops, or stops the whole test after a failed request.
Same user or new user?
In a long timed test, each thread runs its journey many times. If every round must look like a new visitor arriving, the thread should not carry old cookies, caches, and connections into the next round. If every round is the same person continuing to browse, carrying that state is correct. Because the scheduler makes rounds repeat for a long time, this choice has a much bigger effect than in a short test: a wrongly shared state can make the whole run look unrealistically fast, since a visitor who already has everything cached is quick.
Errors and the schedule
The error action interacts with the duration in a quiet but important way. If the action is “stop thread” and the system begins to fail, threads stop one by one long before the duration ends. The active-threads chart then shows a falling staircase in the middle of what should have been a steady plateau. If the action is “stop test”, a single failure can end the whole run early. Make a conscious choice for each test. For a stress test where failures are exactly what you want to observe, continuing is usually better than stopping.
Label differences between versions
Depending on your version of JMeter, the checkbox that unlocks duration and startup delay is called “Scheduler” or “Specify Thread lifetime”. The two fields underneath behave the same way. Do not be alarmed if your screen shows a slightly different label from a tutorial. Look for the two fields measured in seconds, and read the help text of your version if in doubt.
A test plan opened in a newer or older JMeter version may display or round these fields differently. After you change versions, rerun a quick smoke test and check the active-threads chart again.
MMultiple Thread Groups and Staggered Workloads
Real traffic is a mixture of crowds. The scheduler lets each crowd have its own timetable.
A test plan may contain several thread groups, each representing a different kind of user or a different system activity. By default, JMeter starts all the groups at the same time. Giving each group its own startup delay and duration turns the plan into a timetable.
flowchart TD
T["Test starts at 0 s"] --> G1["Group A Browsers: delay 0 s, duration 1800 s"]
T --> G2["Group B Searchers: delay 300 s, duration 1200 s"]
T --> G3["Group C Buyers: delay 600 s, duration 600 s"]
G1 --> E1["Ends near 1800 s"]
G2 --> E2["Ends near 1500 s"]
G3 --> E3["Ends near 1200 s"]
E1 --> END["Test completes when the last group ends"]
E2 --> END
E3 --> END
Running groups one after another
The test plan itself has a checkbox that says to run thread groups consecutively. When it is ticked, JMeter runs the first group completely, then the second, and so on, rather than all at once. This is a different way to make groups follow each other. Use it when groups depend on each other, such as a setup group that must finish before the main test. Use startup delays when groups should overlap in time. Do not mix the two without understanding exactly what you want, because the delays then count from each group’s own start.
A special pair: setUp and tearDown
JMeter offers special groups that run before and after the main test. A setUp group is meant for preparation, such as creating test data. A tearDown group is meant for cleanup. These run in their own phases, so you rarely need startup delays to order them. Their scheduler settings can still be used to limit how long they may run, which is a useful safety measure if preparation might hang.
Designing the mix
Good reasons to stagger
- Different user types really do arrive at different times
- You want to see how the system reacts when heavy users join a quiet system
- You want a quiet start so monitoring can capture a clean baseline
Poor reasons to stagger
- Spreading threads out only because the test machine is weak
- Adding delays you cannot explain to anyone
- Making groups overlap so much that results cannot be attributed to any one of them
When several groups overlap, results from one group are affected by the others. To judge one group fairly, look at a period when only the groups you understand are active, and note which groups were present in each period.
TTest Types and Their Typical Schedules
Different questions need different timelines. The scheduler is how each test type is written down.
| Test type | Question it answers | Typical shape | Typical duration |
|---|---|---|---|
| Smoke test | Does the script work at all? | One or two users, no ramp | One to five minutes |
| Load test | Does the system meet its targets at the expected crowd? | Gentle ramp, long steady stretch | Thirty to sixty minutes |
| Stress test | Where and how does the system break? | Load raised in steps or one slow long ramp | One to several hours |
| Spike test | Can the system survive a sudden crowd and recover? | Very short ramp, short steady stretch, quiet afterwards | Ten to thirty minutes |
| Soak test | Does the system degrade slowly over time? | Moderate steady load, no change | Four to many hours |
Smoke test: prove the script first
Always begin with a tiny test. A smoke test uses one or two threads, a short duration, and no startup delay. It exists to prove that the script logs in, extracts its values, passes its checks, and ends cleanly. Skipping this step and starting a one-hour test with a broken script wastes time and may also disturb the system for no reason.
Load test: the main event
A load test applies the traffic you expect on a busy day. It uses a ramp long enough to be gentle, a steady period long enough to gather plenty of samples, and a short cool-down. The duration is usually thirty to sixty minutes. This is the test whose numbers go into the report.
Spike and stress: the extremes
A spike test shortens the ramp to almost nothing. All the users arrive in seconds, as they might after a link goes viral. A stress test keeps raising the load beyond the expected level until the system shows weakness. The built-in scheduler gives a single steady level, so many teams build stress tests with several thread groups, each joining later with its own startup delay, to create steps. Community plugins offer dedicated groups that draw more complicated shapes, and we discuss them in a later chapter.
Soak test: the marathon
Some problems only appear after hours: slow memory leaks, growing log files, connection leaks, and database tables that become gradually slower. A soak test runs a moderate load for a long time to expose them. Here the scheduler is the main tool, since the whole point is a long and exact duration. Because the test is long, it needs extra care around data, results files, and monitoring, which we cover in the chapters on performance and safety.
Do not try to answer all these questions with one giant test. Run them in order: smoke, then load, then stress or spike, and finally soak. Each result tells you whether it is worth running the next, longer one.
CChoosing the Right Duration
The number you type in the box should come from a reason, not from habit.
Many tests use whatever number the first tutorial used, often 600 or 3600. A better approach is to choose the duration from what you need to learn. Several factors guide the choice.
Enough samples to trust the numbers
Statistics need data. A percentile calculated from fifty samples is shaky, while one calculated from fifty thousand is steady. Estimate the number of samples you will collect by multiplying the expected requests per second by the length of the steady period. If a journey is made of six requests and your target is twenty journeys per second, you will send about one hundred and twenty requests per second. Over a thirty-minute steady period, which is 1800 seconds, that is about two hundred thousand samples, which is plenty. A slower, rarer action, such as a monthly report with only one request per minute, would need a much longer test to collect enough samples.
Long enough for slow effects
Some behaviour needs time to show. A cache that expires every ten minutes needs a test long enough to include several expiry cycles. A scheduled backup job at the server may run every hour. A memory leak of one megabyte per minute is invisible in ten minutes and obvious in ten hours. Ask yourself what is the slowest event you care about, and make the steady period several times longer than that event.
Short enough to afford
Tests cost money and attention. Cloud machines are billed by time, test environments are shared, and long tests make it harder to repeat the test. A good rule is to run the shortest test that gives a trustworthy answer and to repeat it two or three times, rather than running one very long test once. Repeating shows whether your result is stable.
A simple recipe
Write the question
For example: can the checkout hold two hundred orders per minute for half an hour with the ninety-fifth percentile under two seconds?
Choose the steady period
Take the length in the question, here thirty minutes, which is 1800 seconds.
Add warm-up and cool-down
Add a five-minute ramp for warm-up and a short ending. The ramp counts inside the duration.
Set the duration
Duration is steady period plus ramp-up, for example 1800 plus 300 gives 2100 seconds.
Do not forget that duration includes the ramp-up. If you want exactly thirty minutes of steady load and you set the duration to 1800, you will get less than thirty minutes of it, because part of the 1800 seconds is spent ramping.
CCapacity Arithmetic: Duration, Users, and Throughput
A few simple formulas connect the schedule to the load your system actually feels.
The scheduler tells JMeter how long to run, but it does not directly say how much traffic will be produced. The traffic is a result of the number of threads, the time each journey takes, and the pauses between actions. A handful of formulas let you predict it.
Journey time
Add the response times of all requests in the journey to the think time between them. This is how long one user takes to complete one round.
Journeys per user
Divide the steady period in seconds by the journey time. This is how many rounds each user completes.
Journeys per second
Divide the number of threads by the journey time. This is the rate at which the whole crowd starts new journeys.
Requests per second
Multiply journeys per second by the number of requests in one journey. This is the rate the server feels.
Total samples
Multiply requests per second by the steady period in seconds. This tells you how strong your statistics will be.
An example with numbers
Take 600 threads with a journey time of 30 seconds and eight requests in each journey. The crowd starts 600 divided by 30, which is 20 journeys per second. That is 160 requests per second. Over a 1800-second steady period, the test collects about 288,000 samples. If the target for peak hour is 200 requests per second, this test is a little under the target and you would raise the threads or reduce the think time.
Why the journey time changes under stress
Think time stays constant, but response time grows when the system is stressed. A longer response time means a longer journey, which means fewer journeys per second from the same crowd. In other words, a thread group with a fixed number of threads automatically sends fewer requests when the system slows down. This is helpful because it avoids burying a struggling system, but it also means that “the load” you applied dropped exactly when the system suffered. If you need a constant request rate regardless of response time, add a rate-controlling timer or a plugin made for that purpose, and make sure there are enough threads to reach the rate.
Imagine a fixed number of cashiers serving a queue. When customers take longer to pay, each cashier serves fewer people per hour, even though the number of cashiers did not change. Threads are cashiers, and journeys are customers.
CChoosing the Right Startup Delay
A startup delay should always tell a story. If you cannot explain why it is there, remove it.
Where duration is chosen from the question, a startup delay is chosen from the story of the day you are imitating. Real days have a shape: quiet mornings, a lunchtime burst, an evening peak, a sudden email campaign. Startup delays are how you place those events on a timeline. Here are the most useful stories.
Background first, event later
Start steady browsing traffic at time zero and delay a heavy group by ten or twenty minutes. You learn how a busy system reacts when a new wave arrives.
Baseline before load
Give a short delay of a minute or two so monitors record a quiet period. Later you can say exactly how much busier the system became.
Wait for a dependency
If a group needs data that another group creates, delay it long enough for the first group to finish its preparation.
Staircase of load
Several identical groups with delays of ten, twenty, and thirty minutes create a staircase, with the crowd growing in steps.
Think of an orchestra. The strings begin first, the brass joins a few bars later, and the drums come in for the finale. The conductor does not tell everyone to play at once. Startup delays are the conductor’s cues.
Avoid pointless delays
A common mistake is to add a delay of a few seconds to every group “just in case”. It adds nothing, makes the timeline harder to read, and often confuses a later reader who wonders what was supposed to happen in those seconds. Use a delay only when it expresses something about the traffic you are imitating or something you need from the environment.
Use a delay for safety in unattended runs
If a test is started by a pipeline or a scheduled job, a short startup delay can give the environment time to finish a deployment or restart before traffic arrives. This is a pragmatic use, but it is best paired with a proper readiness check in the pipeline, because a fixed delay is only a guess about how long a restart will take. If the guess is wrong, your first minutes of data will be garbage.
When you document a test, write each delay as a sentence: “Buyers start 600 seconds in, because the marketing email goes out ten minutes after the sale opens.” Sentences like this are far more useful than a bare number.
PParameterizing the Schedule with Properties
Hard-coded numbers force you to edit the plan for every run. Properties let one plan serve many runs.
Typing 1800 into the Duration box works, but it ties the plan to one length. The moment someone wants a five-minute smoke test or a four-hour soak test, they must open the plan, edit it, and save it, which invites mistakes. A better way is to read the number from a property, a named setting handed to JMeter when the test starts.
JMeter provides a function for this called the property function. You write it directly in the field, for example ${__P(duration,1800)}. It means: “use the property called duration if it was supplied, otherwise use 1800”. The same idea works for the startup delay, the number of threads, and the ramp-up. When you start the test from the command line, you pass values for these properties, and the same plan becomes a smoke test, a load test, or a soak test without any editing.
| Field | Property approach | Benefit |
|---|---|---|
| Duration | A property with a sensible default | One plan for short and long runs |
| Startup delay | A property per group | Easy to rearrange the timetable |
| Threads and ramp-up | Properties with defaults | Scale load for each environment |
| Target server | A property | The same plan runs against staging or production-like systems |
Always give a default
The second value in the function is the default, used when nobody supplies the property. Choose a small, safe default, such as a short duration, so a run started by accident cannot hammer a system for hours. The default should be the value you would be comfortable with if the person starting the test forgot to set anything.
Making runs reproducible
When settings come from properties, the exact values used for a run can be recorded next to its results, for example in the name of the results folder or in the pipeline log. Months later you can see that a result came from a thirty-minute run with two hundred threads, and you can repeat it exactly. With values hidden inside an edited plan, that history is lost.
A typo in a property name does not cause an error. JMeter quietly uses the default. If your one-hour test mysteriously ran for the default five minutes, check the spelling of the property name on the command line and inside the field.
Debug by printing
While building a plan, it helps to see the values JMeter actually used. A Debug Sampler can show the current properties, and the log records the settings at the start of each group. A thirty-second look at these saves hours of confusion later.
DDistributed Testing and the Scheduler
When one machine is not enough, many machines share the work. The schedule travels with the plan.
In distributed testing, one machine called the controller sends the test plan to several remote machines called engines. Each engine runs the plan on its own and the controller gathers the results. The scheduler works naturally here because the settings are relative: every engine receives the same duration and the same startup delay and counts them from its own start moment.
flowchart TD
C["Controller: sends plan and start command"] --> E1["Engine 1: delay, ramp-up, duration"]
C --> E2["Engine 2: delay, ramp-up, duration"]
C --> E3["Engine 3: delay, ramp-up, duration"]
E1 --> R["Results collected"]
E2 --> R
E3 --> R
R --> C
Important points to remember
- Thread counts multiply. If the plan says one hundred threads and you have five engines, you generate five hundred virtual users. Duration and delay do not multiply; they stay the same on every engine.
- Starts are almost, but not exactly, simultaneous. The controller tells the engines to start one after another, so there may be a small gap of a second or more between them. For tests lasting many minutes this does not matter, but for very sharp spikes it can blur the picture.
- Use the same clock. If you compare JMeter results with server monitoring, make sure all machines agree on the time. A network time service keeps them in step.
- Properties must reach the engines. A setting supplied only on the controller may not be known to the engines. JMeter has a separate way to send properties to the engines, and forgetting it leads to engines using their defaults.
Several buses leave a depot at nearly the same time, each following the same timetable. They each count their trip from their own departure moment. If one leaves a minute late, it arrives a minute late, but the timetable itself is the same for all of them.
In very large distributed tests, you can reduce start gaps by starting engines in groups and giving the groups slightly different startup delays on purpose, or by using a longer ramp-up so a gap of a few seconds is a tiny fraction of the whole.
TTime, Clocks, and Time Zones in Scheduled Tests
A schedule is a promise about time, and time on computers is not as simple as it looks.
The duration and the startup delay are relative: they count seconds from a starting moment. Under the hood, JMeter turns them into absolute moments by reading the computer’s clock. This has a few consequences that are worth knowing before you plan a long or important test.
Relative settings are stable
Because the settings are relative, a test behaves the same whether it starts in the morning or at midnight, in one time zone or another. Daylight saving changes do not matter for the settings themselves, because thirty minutes is always one thousand eight hundred seconds. This is another reason to prefer the built-in fields over writing your own start-time logic.
Timestamps in the results file
Each sample in the results file carries a timestamp. By default it is a number of milliseconds since a fixed starting date, which does not depend on any time zone. That is good, because the numbers from machines in different countries can be compared. When you turn timestamps into readable dates for a report, be careful about which time zone the tool uses, and write the zone next to the times you show to people. A chart that says “peak at ten o’clock” is confusing if the reader lives somewhere else.
Clock jumps
Since JMeter reads the machine’s clock to decide when the end moment has arrived, a sudden jump in the clock during the test can shift the schedule. A time service on the machine might correct a clock that has drifted, and a manual change would do the same. For short tests this is rare. For overnight tests, keep the clocks of all test and server machines synchronised with a trusted time service, and avoid changing them by hand while a test runs.
| Situation | Effect on the schedule | What to do |
|---|---|---|
| Test crosses midnight | None, settings are relative | Nothing, but label dates in reports |
| Daylight saving change | None for durations, but readable times may repeat or skip an hour | Report in a fixed zone such as UTC |
| Clock corrected during the test | The end may come earlier or later than planned | Keep time services running and watch the log |
| Engines with different clocks | Server metrics and JMeter charts may not line up | Synchronise all machines |
For reports that cross teams or countries, use one agreed time zone, and write the start and end times of each phase of the test at the top of the report.
BBeyond the Built-in Scheduler
The built-in scheduler draws a simple shape. Plugins can draw richer ones.
With duration and startup delay, the standard thread group gives a simple shape: wait, ramp up to a fixed level, hold, stop. That is enough for many tests. When you need a shape with several steps, peaks, and valleys, there are two common approaches.
Approach one: several standard groups
You can build steps with several thread groups, each with its own startup delay and duration. It needs no extra software, and every part is visible in the plan. The disadvantage is that the plan becomes long and the thread counts of different groups must be adjusted separately. A staircase with ten steps is ten thread groups.
Approach two: plugin thread groups
The community maintains a collection of plugins, usually installed through a helper called the Plugins Manager. Several of them are made for shaping load over time.
Ultimate Thread Group
Lets you list several rows, each with its own initial delay, ramp-up, hold time, and shutdown time, in a single group. Complex timelines become one table.
Concurrency Thread Group
Describes the target number of concurrent users over time and adds users as needed, which is helpful for step and ramp patterns.
Throughput Shaping Timer
Defines a target request rate over time, and works together with a thread group that supplies enough threads.
Why choose a plugin
- Complicated load shapes are described in one place
- Less duplication than many separate thread groups
- Can aim at a target request rate, not just a user count
Why stay with the built-in
- No extra software to install and keep updated on every machine
- Everyone who knows JMeter understands it at once
- Fewer surprises when upgrading JMeter
Start with the built-in scheduler and only reach for a plugin when the shape you need cannot be written clearly without one. If you do use plugins, install the same versions on the controller and every engine.
RReading Results with the Schedule in Mind
A schedule is only useful if your report respects it. Cut away the warm-up and the tail before you trust any number.
When a scheduled test ends, you have a results file with a row for every sample, including the quiet ramp-up and the untidy tail. If you calculate averages over the whole file, those edges pull the numbers away from the truth. The slow, cold start inflates response times, and the last few cut-off requests add errors.
Find the steady window
The first chart to open is the one showing active threads over time. It should look like a plateau: a rise during ramp-up, a flat top, and a drop at the end. The flat top is your steady window. The HTML dashboard report that JMeter can generate includes this chart, along with response times, throughput, and errors over time. Compare their shapes. Response times that stay flat while threads are flat show a healthy system. Response times that climb during a flat top show something degrading under constant load.
| Period | What it contains | Include in the final numbers? |
|---|---|---|
| Startup delay | No traffic at all | Not applicable |
| Ramp-up | Growing load, cold caches | No, use only to study warm-up behaviour |
| Steady state | Full, stable load | Yes, this is the real result |
| End of duration | Threads stopping, some cut-off requests | No, trim it away |
How to trim
Recent versions of JMeter allow the report generator to be limited to a time window through report properties, so the dashboard covers only the steady period. If your version does not, you can filter the results file by the timestamp column with a spreadsheet or a small script before analysing. Either way, record the exact window you used in the report, so a reader knows which part of the test the numbers describe.
Compare with the plan
Check that what happened matches what you scheduled. Did the group start when it should? Did all threads join? Did the duration end when expected? A group that started late, or a crowd that never reached its full size, tells you that the test did not follow your plan, and any conclusion drawn from it is suspect. The active-threads chart is a lie detector for your schedule.
Do not average over the whole file just because it is easy. Reports that include ramp-up and tail make healthy systems look worse and can also hide real problems inside noise.
TTroubleshooting a Schedule That Does Not Behave
When the clock and the chart disagree, work through the usual suspects in order.
Most scheduler problems have simple causes. The trick is to look at the symptom, match it to a likely cause, and check that cause first. The table below lists the symptoms beginners meet most often.
| Symptom | Likely cause | What to check |
|---|---|---|
| Test ends much earlier than the duration | A finite loop count, or threads stopping after errors or after the data ran out | Loop count box, error action, data file end behaviour |
| Test never ends | Infinite loops with no duration, or the scheduler box not ticked | Scheduler checkbox and a positive number in the duration field |
| Duration seems ignored | The checkbox is off, so the fields are not used | Tick the scheduler or thread lifetime box |
| Nothing happens for a while | A startup delay is set | Delay field, and whether it was meant |
| Fewer users than expected | Ramp-up longer than duration, thread limits on the machine, or errors stopping threads | Active-threads chart, JMeter log, machine metrics |
| Second group starts too early or too late | Delay counts from test start, not from the end of the first group | Add the first group’s delay and duration |
| Test is far too short after a property change | Misspelled property name falling back to the default | Property spelling in the field and at start time |
| More users than planned in distributed mode | Thread counts multiply by the number of engines | Divide threads by engines in the plan |
| Errors appear in the last seconds | Requests cut off when the duration ended | Trim the tail from the report |
A method for any puzzle
Reproduce it smaller
Shrink the test to a few threads and a duration of a minute or two, with the same settings, so you can see the behaviour quickly.
Look at the chart and the log
The active-threads chart shows what happened. The log shows when threads started and stopped, and any warnings.
Change one thing
Alter a single setting at a time and rerun. Changing three things makes it impossible to know which one mattered.
Write down the cause
Add a note to the test plan or the team wiki, so the next person does not repeat the same mistake.
A short, boring smoke test with the real schedule shape and tiny numbers is the cheapest debugging tool you have. Use a duration of one or two minutes, a delay of ten seconds, and a ramp of twenty seconds, and the whole timeline fits on one screen.
MMonitoring, Logging, and Metrics for Timed Tests
A long test is a long watch. Decide in advance what you will watch and who will watch it.
Time-based tests, especially long ones, produce a lot of information. Without a plan for watching it, the problems appear only when the test is over and fixing them means repeating the whole thing. Three kinds of information matter: what JMeter sees, what the system under test shows, and the health of the test machine.
flowchart LR
J["JMeter schedule runs"] --> R["Results file and Backend Listener"]
J --> L["JMeter log"]
SYS["System under test"] --> M["Server monitoring"]
GEN["Load generator machine"] --> M
R --> D["Live dashboard"]
M --> D
L --> D
D --> H["Human watcher with a stop plan"]
What to watch in JMeter
- Active threads over time. It should follow the shape you scheduled. A different shape means something went wrong.
- Throughput. Requests per second should rise with the ramp and settle on the plateau.
- Error rate. A sudden rise during the steady period is a strong signal worth investigating at once.
- Response time percentiles. Watch the ninety-fifth and ninety-ninth, not only the average.
What to watch around JMeter
Watch the processor, memory, disk, and network of the servers under test, because they explain why response times move. Also watch the load generator. If its processor is saturated or its memory is nearly full, your results describe the generator, not the system. The JMeter log should be checked for repeated warnings, which often mean a missing data file or a script that fails after some time.
Live dashboards for long tests
For tests of an hour or more, stream the metrics to a live dashboard using the Backend Listener, which sends data to an external monitoring system while the test is running. A team can then watch the same chart in a meeting room, compare it with server metrics, and decide in time whether to stop. Waiting for a report at the end of an eight-hour soak test only to learn it broke in the first ten minutes is a painful way to learn.
Mark the key moments on your dashboards: when each group’s delay ends, when each ramp-up finishes, and when each duration ends. With these markers, a change in the charts can be matched to its cause at a glance.
PPerformance and Scalability of Long Tests
The longer a test runs, the more the test machine itself has to carry.
A short test can get away with sloppy settings. A long one cannot. Over hours, small inefficiencies add up to full disks, slow garbage collection, and memory pressure. Because the scheduler makes it so easy to run for a long time, you must plan for the cost.
Results file size
Every sample becomes a row in the results file. Suppose your test sends one thousand requests per second for eight hours. That is about twenty-nine million samples. If each row takes about two hundred bytes, the file grows to nearly six gigabytes. Saving response bodies or extra columns makes it much bigger. Plan disk space, choose the columns you need, and consider writing results to a fast disk that is not shared with the operating system.
Memory over time
A listener that keeps results in memory, such as the results tree, grows steadily and will eventually exhaust the memory of the machine. For any long run, use non-GUI mode, remove heavy listeners, and write results straight to a file. Watch the memory and garbage collection of the load generator during the first long test, so you know how it behaves before you trust it overnight.
Data that runs out
With infinite loops and a long duration, a data file that was enough for a five-minute test is used up quickly. Decide what should happen when the data ends: recycle the rows, stop the thread, or stop the test. For tests that create records, think about whether the same row can be used again without breaking the system, for example whether an order number must be unique.
Sessions and tokens
Logins that last a short time will expire during a long test. If the plan logs in only once per thread, the threads will start failing after the token lifetime. Either refresh the token on a schedule or design each iteration to log in again if needed. A soak test that silently becomes an hour of error pages is worse than no test at all, so always keep assertions in place.
Run non-GUI
The graphical window uses memory and processor time and is not meant for load runs.
Keep listeners light
Write results to a file and analyse them after the run.
Plan the space
Estimate samples per second times seconds times bytes per row.
Tune the Java memory
Give the test machine a heap that fits the thread count and watch garbage collection.
AAutomation: Scheduled Tests in Pipelines
The scheduler fits naturally into automated delivery pipelines, because a pipeline needs tests with a known length.
A delivery pipeline is a chain of automatic steps that builds, tests, and releases software. Each step must have a clear start and a predictable end, otherwise the pipeline stalls. A JMeter test with a duration is a good citizen in such a chain: you know before it begins how long it will take, so you can reserve the right amount of time and set a sensible time limit on the step.
flowchart LR
B["Build and deploy"] --> H["Health check: system is ready"]
H --> S["Short smoke run: duration 120 s"]
S --> Q{"Smoke passed?"}
Q -- "Yes" --> L["Load run: duration from property"]
Q -- "No" --> X["Stop pipeline and report"]
L --> G["Quality gate: error rate and percentile limits"]
G --> P["Publish report"]
Two tiers of tests
A common design uses two tiers. On every change, the pipeline runs a short test, perhaps two to five minutes. It catches broken scripts and obvious slowdowns. On a nightly or weekly basis, a longer test of thirty to sixty minutes runs against a more stable environment. Occasionally, before a big event, the team runs a long soak test. All three use the same plan; only the duration and the number of threads change, supplied through properties.
Quality gates
A quality gate is a rule that decides whether the pipeline may continue. After the run, a small script reads the results of the steady window and compares them with agreed limits, such as an error rate below one percent and a ninety-fifth percentile response time under two seconds. If the limits are broken, the step fails and the team is told at once. Since a scheduled test always ends at a known time, the gate can run right after it.
Wait for readiness, not for time
A fixed startup delay is a poor way to wait for a deployment. Deployments take different amounts of time on different days. Instead, let the pipeline poll a health address until the system says it is ready, and then start the test. Use the startup delay only for what it is good at: arranging crowds inside the test timeline.
Always set a maximum time on the pipeline step that is somewhat longer than the longest startup delay plus duration. If a test hangs, the step should fail on its own instead of blocking the pipeline for the whole night.
Shared build machines
Machines that run many jobs are noisy. Another job may use the processor during your test and distort results. For dependable numbers, run the load generator on a machine reserved for the purpose, or at least check the generator’s own metrics during each run so you can discard measurements affected by a busy neighbour.
SSecurity and Safety for Timed and Unattended Tests
A test that runs for hours while nobody watches deserves extra guardrails.
The scheduler makes it simple to start a test that runs for a very long time. That convenience carries responsibility. A load test is real traffic with real credentials, and a mistake that would be small in a five-minute test can become serious in an eight-hour one.
Permission and notice
Run tests only against systems you own or have written approval to test. Agree on the time window with every team that operates the target, the network, and any shared service. A long test that begins at a surprise hour looks like an attack, wakes people up, and may trigger automatic defences that block your generators. Tell people the start time, the end time, and the contact number for stopping it.
Know the stop plan
Before starting, decide how the test will be stopped in an emergency and who is allowed to do it. JMeter can be stopped gracefully, where threads finish current work, or immediately. Operations staff should know that the test is time-limited and when it should end naturally, so a test that continues past its expected end is a clear sign that something is wrong.
Protect secrets for long runs
Keep passwords and tokens out of the saved plan. Provide them at run time as properties or from a protected file. For long tests, results files may contain tokens inside headers or response bodies, so store them securely and delete them when they are no longer needed. Use dedicated test accounts with the smallest rights needed.
Avoid real side effects
A long loop that sends emails, text messages, or payments can create enormous numbers of real events. Always use test data and test endpoints, and confirm that outgoing messages go to a safe place. Think about what the test will leave behind, such as thousands of orders or accounts, and plan the cleanup, perhaps through a tearDown group.
Cost control in the cloud
Cloud machines are billed by time. A test with an unexpectedly long duration, or one that never ends because the loop count and duration were misconfigured, can run up a large bill. Put a limit on the running time of the machines, set alerts on spending, and tear machines down automatically at the end.
Before the test
Get written approval, announce the window, check the numbers in the duration and delay fields, and confirm test data and test endpoints are in use.
During the test
Watch the dashboards, keep the stop plan ready, and compare the live active-threads chart with the plan.
After the test
Confirm the test ended on time, clean up created data, remove cloud machines, and store or delete results according to your rules.
AAdvantages, Disadvantages, and Trade-offs
The built-in scheduler is simple on purpose. Simplicity brings strengths and limits.
Strengths
- Two numbers give a predictable test length
- No extra software to install
- Works the same in the graphical window, on the command line, and across engines
- Combines well with properties for flexible runs
- Staggering several groups creates realistic timelines
Limitations
- Only one steady level per thread group
- The end of a test can be a little untidy for in-flight requests
- Duration includes ramp-up, which beginners often forget
- Complex shapes need many groups or plugins
- The graphical interface does not draw the timeline for you
Time-based versus work-based
The main trade-off is between measuring over a fixed time and measuring a fixed amount of work. A time-based test gives you a predictable calendar. A work-based test, using loop counts, gives you the same number of operations whatever the speed. Time-based tests are better for judging load behaviour. Work-based tests are better when you want to compare the exact same work across two versions of a system. Neither is better in every case, so choose the one that matches your question.
Simplicity versus control
Using only duration and delay keeps a plan easy to read and easy to hand over to a colleague. Plugin thread groups add control but also add things that can break and things people must learn. A good policy is to use the simplest tool that expresses the load you need.
If you can describe your test timeline in one sentence per group, the built-in scheduler is probably enough. If you need a table to describe a single group, think about a plugin.
DDesign Patterns and Anti-patterns
Patterns are habits that keep a schedule healthy. Anti-patterns are habits that quietly spoil results.
Helpful patterns
Timeline first
Draw delay, ramp-up, steady, and end on paper before touching the fields.
Infinite loops with a duration
Let the clock be the only thing that ends a timed test.
Properties with safe defaults
Use the property function so one plan serves short and long runs, and default to something short.
Smoke, then load, then soak
Each test earns the right to run the next, longer one.
One story per delay
Every startup delay is tied to a sentence about real traffic.
Trim before you report
Base conclusions on the steady window only and state the window used.
Anti-patterns to avoid
The pattern
Setting a duration but leaving a small loop count in place.
Why it hurts
Threads finish their loops in minutes and the test ends long before the planned duration, giving far too few samples.
Better approach
Use an infinite loop count whenever the duration should decide the end.
The pattern
A duration shorter than, or equal to, the ramp-up.
Why it hurts
The test never reaches steady state, or ends before all users have joined, so the results describe a load you never intended.
Better approach
Make the duration the steady period plus the ramp-up, and keep the ramp-up a small share of it.
The pattern
Using a long fixed startup delay to wait for a deployment.
Why it hurts
If the deployment is slow, traffic arrives before the system is ready and the first results are garbage. If it is fast, you waste time.
Better approach
Check readiness in the pipeline and start the test when the system answers.
The pattern
Reporting averages over the entire results file.
Why it hurts
Warm-up and cut-off requests at the end distort the numbers and can hide or invent problems.
Better approach
Choose the steady window from the active-threads chart and report only that period, along with percentiles.
The pattern
Starting a long test straight away without a smoke run.
Why it hurts
A small script mistake can waste hours of time, spoil shared environments, and cause pointless alarms.
Better approach
Run a two-minute smoke test with one or two users first, and check every step.
BBest Practices and Common Mistakes
A short checklist to carry into your next test.
Write the question and the timeline
Decide what you want to learn, then convert it to warm-up, steady, and cool-down times.
Use seconds, and double-check the units
Multiply minutes by sixty and hours by thirty-six hundred before typing a number.
Read all thread group fields together
Threads, ramp-up, loop count, scheduler, duration, and delay act as one setting.
Verify with the active-threads chart
After the first run, confirm the shape matches the plan, including when each group starts and ends.
Use properties and defaults
Make duration and delay changeable at start time, with a safe, short default.
Report the steady window
State which seconds of the test the numbers describe.
Repeat before you conclude
Run the same schedule two or three times. One run is an anecdote, several consistent runs are evidence.
Common mistakes in one list
- Typing minutes into a field that expects seconds
- Ticking the scheduler box but leaving the duration blank
- Leaving a finite loop count and expecting the full duration
- Choosing a ramp-up as long as the duration
- Forgetting that the startup delay counts from the test start, not from the end of the previous group
- Adding delays that nobody can explain
- Reading the whole file instead of the steady window
- Running a long test without a stop plan, monitoring, or approval
Build a tiny conversion table in your notes: ten minutes is 600, thirty minutes is 1800, one hour is 3600, four hours is 14400. You will use these four numbers again and again.
RReal-World Scenarios
Four typical situations, described in general terms so you can adapt them.
A ticket sale that opens at noon
A ticketing team wants to see how the site behaves when a popular sale begins. They run a background group of browsers from time zero. A second group of buyers has a startup delay of ten minutes and a very short ramp-up, imitating the rush when the sale opens. They watch the ninety-fifth percentile of the purchase step before and after the buyers arrive, and the quiet start gives them a clean baseline.
An overnight soak test for a payments service
A payments team suspects a slow memory leak. They run a moderate load with a duration of eight hours, an infinite loop count, and a long ramp-up so the service warms up. A live dashboard shows memory use on the server. A rising line that never falls back is the evidence they need, and the schedule makes it a clean, repeatable experiment.
A nightly pipeline check for an API
An API team runs a five-minute scheduled test after every nightly build. Duration and thread counts come from properties with small defaults. A quality gate compares the error rate and ninety-fifth percentile with fixed limits, and the build fails when they are broken. The team catches slowdowns the morning after they were introduced, not weeks later.
A staircase to find the breaking point
A platform team wants to know how many users the system can serve. They create five identical thread groups, each with the same duration but a startup delay ten minutes later than the last. The load grows in steps. They watch which step first brings the error rate above one percent, and that step marks the practical limit.
One plan, many shapes
These four scenarios use the very same thread group elements and samplers. Only the numbers in the scheduler fields, and the way several groups are arranged, change. That is the real value of understanding duration and startup delay: they let a single well-built test plan act as a smoke check, a load test, a spike, a stress staircase, or a soak marathon.
QQuick Reference: Recommended Settings by Goal
A one-page summary you can keep next to your test plan.
When you are in a hurry, start from this table and adjust. It lists sensible starting values for each goal. They are starting points, not rules, so always check them against your own question, your system, and the number of samples you need.
| Goal | Scheduler | Loop count | Startup delay | Duration | Ramp-up |
|---|---|---|---|---|---|
| Smoke check of the script | Optional | Small number | 0 s | 60 to 300 s | A few seconds |
| Normal load test | On | Infinite | 0 to 120 s | 1800 to 3600 s | Under a quarter of the duration |
| Spike test | On | Infinite | Chosen from the story | 300 to 1800 s | Very short |
| Stress staircase | On, in several groups | Infinite | Rising by equal steps | Same for each step | Short for each group |
| Soak test | On | Infinite | Short, for a baseline | 14400 s or more | Long and gentle |
The five questions to ask before pressing start
- Is the scheduler box ticked, and is there a positive number in the duration field?
- Is the loop count infinite, so that the clock decides the end?
- Is the ramp-up clearly shorter than the duration?
- Can I explain every startup delay in one sentence about real traffic?
- Do I know where I will watch the active threads, the error rate, and the response time percentiles?
If you can answer yes to all five questions, you are ready. If any answer is no, fix that first. It costs a minute now and may save an entire test run.
FFrequently Asked Questions
Quick answers to the questions beginners ask most often.
SSummary and Key Takeaways
The JMeter scheduler gives a thread group a place on the timeline of a test. Startup delay says when the group begins, and duration says how long it lives. Together with the ramp-up and the loop count, these settings turn a plain crowd of virtual users into a planned performance experiment with a start, a steady middle, and an end. If you remember one idea, let it be that every number in the thread group works together, and a trustworthy test is one where you can explain every second of its timeline.
Key Takeaways
- Duration sets the lifetime of the group. It is measured in seconds and includes the ramp-up.
- Startup delay postpones the group. It is relative to the test start and is the main tool for staggering several groups.
- Use an infinite loop count with a duration. Otherwise the loops may end the test before the clock does.
- Keep ramp-up small compared with duration. Otherwise there is no steady state to measure.
- Read the active-threads chart. It proves the test followed the plan, and shows the steady window to report.
- Parameterize with properties. One plan can serve smoke, load, and soak runs, with safe default values.
- Plan long tests carefully. Budget disk and memory, keep a stop plan, get approval, protect secrets, and watch costs.