The ramping-vus executor (also known as stages) gradually increases or decreases the number of VUs over defined time periods. This is the most common executor for realistic load testing, as it allows you to simulate traffic patterns that ramp up, sustain, and ramp down.
How It Works
With ramping VUs:
- VUs start at
startVUs (or ramp from 0)
- VUs increase/decrease linearly to reach each stage’s
target
- Each stage has a
duration and target VU count
- VUs continuously run iterations throughout all stages
- Ramping is smooth and linear between targets
VUs ^
100 | ╱‾‾‾‾‾‾‾‾╲
75 | ╱ ╲
50 | ╱ ╲
25 | ╱ ╲
0 |╺━━╯ ╲___
+---------------------------------> time
2m 5m 3m 2m 2m
(stages)
Configuration
Number of VUs to start with. Can be 0.
Array of stage objects defining the VU ramping pattern. Each stage must have duration and target.
Duration of this stage. Can be 0 for instant VU changes.
Target number of VUs at the end of this stage.
Time to wait for iterations to finish when ramping down VUs. This is separate from gracefulStop.
Example
Classic Load Test Pattern
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
scenarios: {
load_test: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 10 }, // Ramp up to 10 VUs over 2 minutes
{ duration: '5m', target: 10 }, // Stay at 10 VUs for 5 minutes
{ duration: '2m', target: 50 }, // Ramp up to 50 VUs over 2 minutes
{ duration: '5m', target: 50 }, // Stay at 50 VUs for 5 minutes
{ duration: '2m', target: 0 }, // Ramp down to 0 VUs over 2 minutes
],
gracefulRampDown: '30s',
},
},
};
export default function () {
http.get('https://test.k6.io');
sleep(1);
}
Spike Test
export const options = {
scenarios: {
spike: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '10s', target: 10 }, // Baseline
{ duration: '0s', target: 100 }, // Instant spike to 100 VUs
{ duration: '1m', target: 100 }, // Sustain spike
{ duration: '10s', target: 10 }, // Quick recovery
{ duration: '3m', target: 10 }, // Observe recovery
{ duration: '10s', target: 0 }, // Ramp down
],
},
},
};
Stress Test - Find Breaking Point
export const options = {
scenarios: {
stress: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 50 },
{ duration: '2m', target: 100 },
{ duration: '2m', target: 150 },
{ duration: '2m', target: 200 },
{ duration: '2m', target: 250 },
{ duration: '2m', target: 300 },
{ duration: '5m', target: 0 }, // Gradual ramp down
],
},
},
thresholds: {
http_req_failed: ['rate<0.1'], // Less than 10% errors
http_req_duration: ['p(95)<2000'], // 95% under 2s
},
};
When to Use
Use the ramping VUs executor when:
- You want to simulate realistic traffic patterns
- You need to test how your system handles increasing load
- You’re performing stress testing to find breaking points
- You want to observe system behavior during ramp-up and ramp-down
- You need to give your system time to warm up before peak load
- You’re testing auto-scaling behavior
Behavior Details
Linear Ramping
VUs increase/decrease linearly between targets:
stages: [
{ duration: '60s', target: 60 },
]
// At t=0s: 0 VUs
// At t=10s: 10 VUs
// At t=30s: 30 VUs
// At t=60s: 60 VUs
Zero-Duration Stages
Use duration: '0s' for instant VU changes:
stages: [
{ duration: '1m', target: 10 },
{ duration: '0s', target: 100 }, // Instant jump to 100 VUs
{ duration: '1m', target: 100 },
]
Graceful Ramp Down
When ramping down, VUs get gracefulRampDown time to finish their current iteration:
export const options = {
scenarios: {
example: {
executor: 'ramping-vus',
startVUs: 100,
stages: [
{ duration: '5m', target: 100 },
{ duration: '2m', target: 10 }, // Ramping down
],
gracefulRampDown: '30s', // Each VU has 30s to finish
},
},
};
Maximum VUs Reservation
k6 pre-allocates the maximum number of VUs needed across all stages:
stages: [
{ duration: '1m', target: 50 },
{ duration: '2m', target: 100 }, // Peak: 100 VUs
{ duration: '1m', target: 25 },
]
// k6 will initialize 100 VUs at test start
Common Load Test Patterns
Soak Test
Sustained load over a long period:
stages: [
{ duration: '5m', target: 50 }, // Ramp up
{ duration: '3h', target: 50 }, // Soak at 50 VUs for 3 hours
{ duration: '5m', target: 0 }, // Ramp down
]
Breakpoint Test
Continually increase until failure:
stages: [
{ duration: '5m', target: 100 },
{ duration: '5m', target: 200 },
{ duration: '5m', target: 300 },
{ duration: '5m', target: 400 },
{ duration: '5m', target: 500 },
// Continue until system breaks...
]
Wave Pattern
Simulate traffic waves:
stages: [
{ duration: '30s', target: 20 }, // Wave 1 up
{ duration: '30s', target: 10 }, // Wave 1 down
{ duration: '30s', target: 30 }, // Wave 2 up
{ duration: '30s', target: 15 }, // Wave 2 down
{ duration: '30s', target: 40 }, // Wave 3 up
{ duration: '30s', target: 0 }, // Wave 3 down
]
Advanced Configuration
Multiple Ramping Scenarios
export const options = {
scenarios: {
api_traffic: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '5m', target: 50 },
{ duration: '10m', target: 50 },
{ duration: '5m', target: 0 },
],
exec: 'apiTest',
tags: { scenario: 'api' },
},
web_traffic: {
executor: 'ramping-vus',
startVUs: 0,
startTime: '2m', // Start 2 minutes later
stages: [
{ duration: '5m', target: 100 },
{ duration: '10m', target: 100 },
{ duration: '5m', target: 0 },
],
exec: 'webTest',
tags: { scenario: 'web' },
},
},
};
export function apiTest() {
http.get('https://test.k6.io/api');
}
export function webTest() {
http.get('https://test.k6.io');
}
Metrics
The executor emits these metrics:
iterations - Total completed iterations
iteration_duration - Time to complete each iteration
vus - Current number of active VUs (changes over time)
vus_max - Maximum number of VUs (from peak stage)
Validation
The executor validates that VU targets don’t exceed the sanity limit of 100 million VUs.
// ❌ Invalid - exceeds max VUs
stages: [
{ duration: '1m', target: 100000001 }, // Error!
]
// ❌ Invalid - no stages defined
stages: [] // Error!
// ❌ Invalid - negative target
stages: [
{ duration: '1m', target: -10 }, // Error!
]
Best Practices
- Start from zero: Begin with
startVUs: 0 to see system behavior from cold start
- Include ramp-up: Give your system time to warm up (caches, connection pools, etc.)
- Sustain peak load: Hold peak load long enough to observe steady-state behavior
- Gradual ramp-down: Avoid instant drops to observe system recovery
- Set gracefulRampDown: Allow iterations to complete when ramping down
- Monitor throughout: Watch metrics during all stages, not just peak
- Use realistic patterns: Model actual traffic patterns from your production data
Comparison with Other Executors
| Feature | Ramping VUs | Constant VUs | Ramping Arrival Rate |
|---|
| VU count | Variable over stages | Fixed | Variable (auto-scaled) |
| Complexity | Medium | Low | High |
| Iteration rate | Varies with VUs | Constant per VU | Fixed (configured) |
| Best for | Realistic load patterns | Steady state | Fixed throughput |
See Also