A common mistake in performance testing is analyzing the wrong data. The first few minutes of a test rarely represent the system's real behavior — and the last few minutes may be contaminated by shutdown effects.
Understanding the warm-up and steady state phases is essential to correctly interpret results and make decisions based on valid data.
Measuring a cold system is like evaluating an athlete before warm-up.
Test Phases
1. Ramp-up
Period of gradual load increase to the desired level.
Load
│ ╭────────────
│ ╱
│ ╱
│ ╱
│ ╱
│───╱
└────────────────────────
Ramp Steady State
Why do ramp-up:
- Avoids shocking the system
- More realistic (users don't all arrive at once)
- Allows identifying at which point the system starts to degrade
2. Warm-up
Initial period where the system is still "warming up".
What happens during warm-up:
- JIT compilation (Java, .NET, Node.js)
- Cache filling
- Connection pool establishment
- Initial memory allocation
- Data loading into memory
Results during warm-up:
- Higher than normal latency
- Lower throughput
- Erratic behavior
3. Steady State
Stable state where the system operates under normal conditions.
Characteristics:
- Metrics stabilize
- Consistent latency
- Predictable throughput
- Stable resource usage
This is where you measure.
4. Cool-down / Ramp-down
Period of gradual load reduction.
Why do it:
- Avoids accumulation of pending requests
- Allows observing system recovery
- More realistic
Why Warm-up Matters
JIT Compilation
Languages like Java, C#, and JavaScript (V8) compile code at runtime:
First execution: interpreted → slow
Subsequent executions: compiled → fast
The first requests can be 10-100x slower than subsequent ones.
Cold caches
Systems depend on multiple cache layers:
- Application cache
- Database cache
- Operating system cache
- CPU cache
Empty caches = more I/O = higher latency.
Unestablished connections
- Database connection pools still empty
- HTTP connections not yet established
- SSL handshakes not yet done
Lazy loading
Many frameworks load resources on demand:
- Classes loaded on first use
- Configurations read on first request
- Dependencies initialized late
Identifying Steady State
Visually
Latency
│
│╲
│ ╲
│ ╲────────────────────
│
└────────────────────────
Warm-up │ Steady State
The curve flattens when steady state is reached.
Statistically
Calculate metric variation in time windows:
If standard deviation(latency) in last 5 min
< 10% of mean
→ probably in steady state
Common heuristics
| System | Typical warm-up time |
|---|---|
| Java (Spring) | 2-5 minutes |
| .NET | 1-3 minutes |
| Node.js | 30s-2 minutes |
| Go | 10-30 seconds |
| Python | 30s-1 minute |
Note: this varies a lot with the specific application.
Configuring Warm-up in Tests
Minimum recommended time
Total test duration = Ramp-up + Warm-up + Steady State + Cool-down
Example:
- Ramp-up: 2 minutes
- Warm-up: 5 minutes (discarded in analysis)
- Steady State: 15 minutes (measurement period)
- Cool-down: 2 minutes
Total: 24 minutes
Excluding warm-up from analysis
Option 1: Configure in script
// k6 example
export const options = {
stages: [
{ duration: '2m', target: 100 }, // ramp-up
{ duration: '5m', target: 100 }, // warm-up (tag for exclusion)
{ duration: '15m', target: 100 }, // steady state
{ duration: '2m', target: 0 }, // cool-down
],
};
Option 2: Filter in analysis Discard the first N minutes when calculating metrics.
Option 3: Pre-warm before test Run a light load before the real test to warm up the system.
Warm-up in Production
The cold start problem
New instances in production also suffer from warm-up:
- Rolling deploys
- Autoscaling
- Failure recovery
Mitigation strategies
1. Smart readiness probes Don't mark the instance as ready until it's warmed up.
2. Pre-warming Send synthetic requests to new instances before receiving real traffic.
3. Graceful startup Gradually increase traffic to new instances.
4. Keep warm pool Maintain extra already-warmed instances ready to receive traffic.
Common Mistakes
1. Tests too short
5 minutes of testing
= 2 min ramp + 3 min steady
= insufficient data
Recommendation: minimum 15-20 minutes of steady state.
2. Including warm-up in metrics
Including the first minutes distorts all statistics:
- Inflated average
- Wrong percentiles
- Underestimated throughput
3. Not warming up between iterations
When running multiple tests, the system may cool down between them. Consider:
- Continuous tests
- Warm-up period between iterations
4. Forgetting dependency warm-up
Your system may be warm, but:
- Database is cold
- Cache was cleared
- CDN doesn't have content at edge
Conclusion
Warm-up and steady state are fundamental concepts for reliable performance tests.
For valid tests:
- Include adequate ramp-up period
- Wait for the system to reach steady state
- Exclude warm-up from final metrics
- Keep steady state long enough for meaningful data
- Consider external dependency warm-up
For production:
- Plan for cold starts in deploys and autoscaling
- Implement pre-warming when possible
- Use readiness probes that consider warm-up
The true system behavior only appears after it warms up. Measuring before that is measuring the exception, not the rule.