Skip to content

Ramp-up, think time, and pacing

A realistic load profile is not just a number of virtual users. It is a shape: how load builds up, how users behave between requests, and how the arrival rate is paced over time. Three controls govern 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. Rather than throwing the full load at the system immediately, 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 a full-load condition simultaneously. Cache misses, connection pool initialization, and JVM warm-up all happen at once. 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

The ramp-up duration should be long enough that each step in VU count has time to stabilize. A rule of thumb: ramp-up ≥ 2× the p95 latency of a single request. For a 500 ms p95, 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 — 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

Adding realistic think time is often what makes a 100-VU test represent the behavior of 100 real users, rather than 100 bots hammering 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 specify it per-request for more precise control.

Fixed think time is unrealistic — 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, producing a more natural load shape.

Pacing controls when each VU iteration starts — it enforces a minimum duration for each scenario loop. Where think time pauses within a scenario, 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:

  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 explicitly 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 — it artificially lowers the steady-state result.
Use random think time distributions to avoid synchronized waves of requests.Use fixed think time for all VUs — synchronized arrivals create artificial load spikes.