Ramp-Up Period in Load Testing

The ramp-up period is the time a load test takes to climb from zero to its target load, either by starting virtual users gradually or by increasing the request rate. Choose it so the system can adjust the way it would in production: long enough for autoscaling, connection pools and caches to catch up (typically 2 to 5 minutes for a web app or API), and never so long that it eats the steady-state time you actually measure. Results collected during the ramp describe the ramp, not the system at target load.
What the ramp-up period controls
Ramp-up sets the slope of the load curve. In a VU-based (closed) test it is how fast new virtual users start. In an arrival-rate (open) test it is how fast the requests per second rise. The slope decides three things:
- Connection setup rate. Each new VU usually opens a new TCP and TLS connection. 2,000 VUs started in 1 second is 2,000 handshakes per second against your load balancer, on top of the requests themselves.
- Time for adaptive systems to react. Autoscalers, connection pools, JIT compilers and caches all respond to load with a delay. A ramp faster than that delay overloads the system before it adapts.
- What your results mean. A slow ramp approximates organic traffic growth. A ramp of a few seconds is a spike test. Both are valid, but they answer different questions.
The two most common mistakes come from treating ramp-up as a cosmetic setting: ramping in seconds and calling the result a load test, or leaving the ramp inside the measured summary.
The formulas
VU ramps
VU start rate (VUs/s) = target VUs / ramp-up seconds
interval between VU starts = ramp-up seconds / target VUs
RPS during ramp ≈ VUs(t) / (response time + think time)
Example: JMeter with 300 threads and a 60-second ramp-up starts one thread every 0.2 s, 5 threads per second. If each thread runs a request with 200 ms response time and 1.8 s think time, each thread produces 0.5 RPS, so load rises by about 2.5 RPS every second and reaches 150 RPS at the 60-second mark. The relationship between VUs and RPS is covered in VUs vs RPS.
Note the last formula. In a closed model, if the server slows down during the ramp, response time grows and RPS grows more slowly than VUs. The ramp partly hides the overload it causes. An arrival-rate ramp does not have this problem, which is one reason to prefer it when you care about latency at a specific RPS (see open vs closed workload models).
Arrival-rate ramps
ramp slope (RPS/s) = (target RPS − start RPS) / ramp-up seconds
VUs needed at peak ≈ target RPS × (p99 response time in s) × 1.5 safety margin
Example: going from 50 to 1,000 RPS over 3 minutes is a slope of about 5.3 RPS per second. If p99 at peak is 400 ms, you need at least 1,000 × 0.4 × 1.5 = 600 VUs available, or the generator will silently fall behind the schedule.
How to choose a ramp-up period
Start from whichever of these lead times is longest in your stack, then add a margin.
1. Autoscaling lead time
The ramp should not outrun the time it takes to add capacity, unless outrunning it is the point of the test. For a Kubernetes HorizontalPodAutoscaler, one scale-up cycle is roughly: metrics collection and the HPA sync loop (15 s by default), pod scheduling, image pull if not cached, container start, and readiness probe. 45 to 90 seconds per cycle is typical for a warm node pool. If the cluster also needs new nodes, add the node provisioning time, often a few minutes. The default HPA scale-up policy allows adding at most 4 pods or 100% of current pods, whichever is more, every 15 seconds.
Worked example (illustrative numbers): each pod handles 100 RPS, 4 pods are running, and the target is 1,200 RPS. One scale cycle takes about 90 s. After the first cycle there are 8 pods (800 RPS of capacity), after the second 16 pods (1,600 RPS). A ramp that stays below capacity therefore reaches 800 RPS no sooner than 90 s and 1,200 RPS no sooner than 180 s. A 3 to 4 minute ramp tests the steady system; a 30-second ramp tests autoscaling lag and will show errors that real users would only see during a sudden spike. Both are worth running, labeled separately. The autoscaling too slow page covers what to tune when the second test fails.
2. Cache warm-up
A cold cache sends every request to the database. If your production traffic never sees a fully cold cache (because deploys are rolling and caches are shared), a fast ramp against a cold cache overstates database load. Either ramp slowly enough that the hit ratio reaches its normal level before full load, or pre-warm with a short read-only run. If the cache does start cold in production, for example after a full flush or a region failover, test that explicitly as its own scenario.
3. Connection setup
Keep the new-connection rate within what your edge can accept. On Linux, net.core.somaxconn defaults to 4096 on kernels 5.4 and later (128 on older kernels), and nginx uses a listen backlog of 511 by default on Linux. A ramp that opens thousands of connections per second can overflow these queues and produce connection reset by peer or connect timeouts that are artifacts of the ramp, not of steady load. See connection reset by peer for the kernel side.
4. The duration budget
Ramp time comes out of your total test duration. If a tool or plan caps a single test at 20 minutes, a 4-minute ramp leaves about 15 minutes of steady state after a 1-minute ramp-down. With a 5-minute cap, a 1-minute ramp is the most you can afford. How long a load test should run covers the steady-state side of this budget.
Ramp-up ≥ 2 × the slowest adaptation in your stack (autoscaling cycle, pool growth, cache warm-up), with a floor of about 1 minute for load tests and a ceiling of about 25% of the total test duration.
Step vs linear ramps
| Profile | Best for | How to read results | Watch out for |
|---|---|---|---|
| Linear ramp + hold | Load tests at one known target | Only the hold window counts | Ramp too short for autoscaling |
| Step ramp | Capacity and stress tests, finding the knee | One p95/throughput point per plateau, after discarding the first 30-60 s of each step | Steps too short to stabilize; too many steps for the duration cap |
| Continuous slow ramp | Quick breakpoint search | Plot latency against RPS and look for the bend | Every sample is taken mid-transition, so numbers are optimistic |
| Spike | Flash sales, push notifications, retries after an outage | Peak error rate and time to recover to baseline p95 | Calling it a load test; skipping the recovery period |
Step ramps are the most informative shape for capacity work because each plateau gives a clean measurement. With a 20-minute budget, five steps of 3.5 minutes plus a short ramp-down is a good layout. Plot each plateau's p95 against its throughput and you have the curve described in throughput vs latency.
Ramp configuration in common tools
k6 VU stages, ramping to 200 VUs over 3 minutes, holding, then ramping down:
export const options = {
stages: [
{ duration: '3m', target: 200 },
{ duration: '12m', target: 200 },
{ duration: '1m', target: 0 },
],
};
k6 arrival-rate ramp, which keeps the request schedule independent of response times:
export const options = {
scenarios: {
ramp_rps: {
executor: 'ramping-arrival-rate',
startRate: 50, timeUnit: '1s',
preAllocatedVUs: 300, maxVUs: 600,
stages: [
{ duration: '3m', target: 1000 },
{ duration: '12m', target: 1000 },
],
},
},
};
Locust sets the ramp with a spawn rate in users per second: locust -u 500 -r 5 reaches 500 users after 100 seconds. In JMeter's Thread Group, the "Ramp-up period (seconds)" field spreads thread starts evenly; for steps, use a stepping or concurrency thread group plugin. In LoadTester, account for ramp time within the plan's maximum test duration and set thresholds on the steady portion you care about.
Ramp-down
Ramp-down matters less for measurement but it is not free:
- Graceful stop. Stopping all VUs at once aborts in-flight requests, which can show up as client-side errors or half-finished transactions. k6's
gracefulRampDown(default 30 s) lets iterations finish. - Recovery observation. After a stress or spike test, drop to normal load rather than zero and watch how long p95 and error rate take to return to baseline. A system that recovers in 20 seconds and one that needs 10 minutes because of a retry backlog are very different (see retry storm under load).
- Scale-down behavior. Autoscalers usually scale down slowly by design (the HPA default stabilization window for scale-down is 5 minutes). Back-to-back runs started before scale-down finishes begin with extra capacity and give better numbers than a fresh run.
Common ramp-up mistakes
- Measuring the ramp. A 15-minute test with a 10-minute linear ramp reports percentiles that mostly describe partial load. Keep the ramp under about 25% of the run and exclude it.
- Ramping faster than the autoscaler and calling it a capacity result. If the errors stop once the new pods are ready, you found a scaling-lag problem, not a capacity limit.
- Zero ramp. Starting every VU at second 0 synchronizes them: they all send their first request together and then move in lockstep for a while, producing bursty load and inflated latency.
- Ramp in VUs, target in RPS. If the target is 1,000 RPS but the test ramps VUs, a slowing server quietly lowers RPS. Verify the achieved RPS at the end of the ramp, or ramp the arrival rate directly.
- Different ramps between runs you compare. A regression check is only valid if ramp, duration and data are identical to the baseline.
Ramp-up checklist
- Write down the question: steady capacity (slow ramp) or reaction to sudden load (spike).
- Measure your slowest adaptation: autoscaling cycle, cache warm-up, pool growth.
- Set ramp-up to at least 2x that time, within about 25% of total duration.
- Check the new-connection rate against your edge's backlog and connection limits.
- For capacity work, use steps of 3 to 5 minutes and discard the first 30 to 60 s of each.
- Exclude the ramp from pass/fail percentiles and record achieved RPS at the end of the ramp.
- Ramp down to normal load, not zero, when you need to measure recovery.
FAQ
What is a good ramp-up time for 1,000 users?
There is no fixed number of users per second; it depends on how fast your system adapts. For a typical web app with autoscaling, 2 to 5 minutes to reach 1,000 VUs (roughly 3 to 8 new VUs per second) is a sensible start. If you do not autoscale and caches are warm, 1 minute is often enough.
What does ramp-up period mean in JMeter?
It is the time JMeter takes to start all threads in a Thread Group, spread evenly. With 100 threads and a 50-second ramp-up, one thread starts every 0.5 seconds. It does not control requests per second directly; that also depends on response time and timers.
Should results during ramp-up be included in the report?
Not in the pass/fail percentiles, because the system is not yet at target load and may still be warming up or scaling. Keep the ramp data to explain autoscaling and warm-up behavior. Report steady-state numbers separately.
Is a ramp-up the same as a spike test?
A spike test is a ramp so short, usually seconds, that adaptive systems cannot react in time. It answers how the system behaves under sudden load and how fast it recovers. A normal ramp-up deliberately gives the system time to adapt so you can measure steady capacity.
Why do I get connection errors only at the start of the test?
A fast ramp opens many TCP and TLS connections at once and can overflow listen backlogs, connection limits or pools that grow lazily. Errors that disappear once the ramp ends usually point to connection setup rate, not steady-state capacity. Lengthen the ramp or raise the backlog and pool limits.