Skip to content

Ramp-up, think time, and pacing

A realistic load profile has a shape as well as a number of virtual users: how load builds up, how users behave between requests, and how the arrival rate is paced over time. Three controls set that shape: ramp-up, think time, and pacing.

Ramp-up is the period at the start of a run during which MaxoPerf gradually increases the VU count from 0 to the target concurrency. Instead of hitting the system with the full load at once, a ramp-up gives the system (and your monitoring) time to stabilize.

Without a ramp-up, the system has to handle a cold-start spike and full load at the same time. Cache misses, connection pool initialization, and JVM warm-up all happen together. The first 30 seconds of a no-ramp-up test often look worse than steady-state behavior, and that inflates your latency results.

With a ramp-up, you can identify:

  • When the system stabilizes at each concurrency level.
  • At what VU count latency starts to climb (capacity discovery).
  • Whether warm-up artifacts are polluting the results.
execution:
- concurrency: 200
ramp-up: 3m # 3-minute ramp from 0 to 200 VUs
hold-for: 10m # 10-minute steady-state hold
scenario: checkout-flow

Make the ramp-up long enough for each step in VU count to stabilize. A rule of thumb: ramp-up ≥ 2× the p95 latency of a single request. For a 500 ms p95, a ramp-up of at least 1 minute is typical. For a 5 s p95, use 5+ minutes.

In the MaxoPerf Overview tab, the throughput chart shows a rising line during ramp-up that levels off when the full VU count is reached. Latency should stabilize shortly after. If latency keeps climbing after ramp-up ends, the system is not at steady state. Extend the hold period or lower the VU count.

Think time is the pause a virtual user waits between completing one request and starting the next. It simulates a real user reading a page, filling out a form, or clicking a link.

Think time affects concurrency. With zero think time, every VU is always in flight, so concurrency equals VU count. With 5 seconds of think time and a 200 ms request, each VU is in flight only about 4% of the time. The resulting concurrency is much lower than the VU count.

Think time also affects RPS. The relationship:

RPS ≈ VU count / (avg response time + think time)

At 100 VUs, 200 ms response time, and 2 s think time:

RPS ≈ 100 / (0.2 + 2.0) = ~45 RPS

Realistic think time is often what makes a 100-VU test behave like 100 real users instead of 100 bots hitting the API as fast as possible.

scenarios:
checkout-flow:
think-time: 2s
requests:
- url: ${TARGET_URL}/api/v1/products
label: list-products
- url: ${TARGET_URL}/api/v1/cart/add
method: POST
label: add-to-cart
- url: ${TARGET_URL}/api/v1/checkout
method: POST
label: checkout

The think-time at the scenario level applies between requests. You can also set it per request for finer control.

Fixed think time is unrealistic, because real users don’t wait exactly 2.0 seconds. Taurus supports a uniform random distribution:

think-time: uniform(1s, 3s)

This draws a random wait between 1 and 3 seconds for each think pause, which gives a more natural load shape.

Pacing controls when each VU iteration starts. It enforces a minimum duration for each scenario loop. Think time pauses within a scenario, and pacing controls the between-loop gap.

If you want each VU to complete no more than one scenario per 30 seconds regardless of how fast the requests are:

scenarios:
checkout-flow:
keepalive: false
requests:
- …
# In JMeter: use Constant Throughput Timer or Flow Control Action

Pacing is most useful when:

  • You want to limit the maximum RPS from a closed workload model.
  • You want the VU count to represent hourly active users, not concurrent-per-second users.
  • You are modeling batch jobs or scheduled operations with fixed cadence.

Ramp-up, think time, and pacing together produce the load shape: the profile of throughput over time. A well-designed profile looks like this:

  1. Ramp phase: throughput rises steadily.
  2. Steady-state hold: throughput plateaus. This is the measurement window.
  3. Ramp-down (optional): throughput drops gracefully.

The steady-state window is where your results are meaningful. If your test has no hold phase, you are measuring ramp-up behavior and calling it steady state.

DoDon’t
Use a ramp-up of at least 2× the p95 latency to let the system stabilize.Start a test at full load with no ramp-up if you want steady-state latency numbers.
Add think time that reflects how real users interact. Check your analytics for session data.Use 0 think time for every test as the default. It produces unrealistic results unless you are deliberately modeling API clients with no human think time.
Treat the ramp-up window as a warm-up; focus your analysis on the steady-state hold window.Average latency across the entire run including ramp-up. The low-load ramp pulls the steady-state result down.
Use random think time distributions to avoid synchronized waves of requests.Use fixed think time for all VUs. Synchronized arrivals create artificial load spikes.