The ramping-arrival-rate executor starts iterations at a variable rate that changes over defined stages. This combines the throughput-focused approach of arrival rate executors with the flexibility of ramping patterns.
How It Works
With ramping arrival rate:
- Iteration rate starts at
startRate per timeUnit
- Rate increases/decreases linearly to each stage’s
target
- k6 automatically allocates VUs to maintain the target rate
- VUs scale up/down dynamically as the rate changes
- If
maxVUs is insufficient, iterations are dropped
Rate ^
(iters/sec)
100 | ╱‾‾‾‾‾╲
75 | ╱ ╲
50 | ╱ ╲___
25 | ╱ ╲
0 |╺━━╯ ╲___
+--------------------------------> time
2m 3m 2m 1m 2m
(stages)
VUs dynamically adjust to maintain rate
Configuration
Must be ramping-arrival-rate
Number of iterations to start per timeUnit. Can be 0.
Period over which startRate and stage targets are calculated.
Array of stage objects defining the iteration rate pattern.
Target iteration rate at the end of this stage (per timeUnit).
Number of VUs to pre-allocate before test start.
maxVUs
integer
default:"preAllocatedVUs"
Maximum number of VUs allowed. Cannot be less than preAllocatedVUs.
Example
Progressive Load Test
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
scenarios: {
progressive_load: {
executor: 'ramping-arrival-rate',
startRate: 0,
timeUnit: '1s',
preAllocatedVUs: 50,
maxVUs: 200,
stages: [
{ duration: '2m', target: 10 }, // Ramp to 10 iters/s
{ duration: '5m', target: 10 }, // Hold at 10 iters/s
{ duration: '2m', target: 50 }, // Ramp to 50 iters/s
{ duration: '5m', target: 50 }, // Hold at 50 iters/s
{ duration: '2m', target: 100 }, // Ramp to 100 iters/s
{ duration: '5m', target: 100 }, // Hold at 100 iters/s
{ duration: '2m', target: 0 }, // Ramp down
],
},
},
};
export default function () {
http.get('https://test.k6.io');
sleep(1);
}
Breakpoint Test - Find Rate Limit
import http from 'k6/http';
export const options = {
scenarios: {
find_breakpoint: {
executor: 'ramping-arrival-rate',
startRate: 0,
timeUnit: '1s',
preAllocatedVUs: 100,
maxVUs: 1000,
stages: [
{ duration: '5m', target: 100 },
{ duration: '5m', target: 200 },
{ duration: '5m', target: 400 },
{ duration: '5m', target: 800 },
{ duration: '5m', target: 1600 },
],
},
},
thresholds: {
http_req_failed: ['rate<0.05'],
http_req_duration: ['p(95)<2000'],
},
};
export default function () {
http.get('https://test.k6.io/api');
}
Traffic Pattern Simulation
import http from 'k6/http';
export const options = {
scenarios: {
daily_pattern: {
executor: 'ramping-arrival-rate',
startRate: 10, // Night traffic: 10 RPS
timeUnit: '1s',
preAllocatedVUs: 20,
maxVUs: 300,
stages: [
// Morning ramp-up
{ duration: '2m', target: 50 }, // 6-8 AM
{ duration: '3m', target: 100 }, // 8-11 AM
// Lunch spike
{ duration: '1m', target: 150 }, // 11 AM-12 PM
{ duration: '2m', target: 150 }, // 12-2 PM
{ duration: '1m', target: 100 }, // 2-3 PM
// Afternoon
{ duration: '3m', target: 80 }, // 3-6 PM
// Evening spike
{ duration: '1m', target: 120 }, // 6-7 PM
{ duration: '2m', target: 120 }, // 7-9 PM
// Night ramp-down
{ duration: '2m', target: 50 }, // 9-11 PM
{ duration: '2m', target: 10 }, // 11 PM-1 AM
],
},
},
};
export default function () {
http.get('https://test.k6.io');
}
When to Use
Use the ramping arrival rate executor when:
- You need to test varying throughput over time
- You want to find the maximum sustainable request rate
- You’re simulating realistic traffic patterns with peaks and valleys
- You need to test auto-scaling response to changing load
- Iteration duration varies and you want consistent throughput
- You’re testing rate limiting under varying load
- You want to observe system behavior as load increases gradually
Behavior Details
Linear Rate Ramping
Iteration rate changes linearly between stage targets:
stages: [
{ duration: '60s', target: 60 },
]
// At t=0s: 0 iters/s
// At t=10s: 10 iters/s
// At t=30s: 30 iters/s
// At t=60s: 60 iters/s
Dynamic VU Scaling
VUs automatically scale to maintain the target rate:
// If iteration duration is 200ms:
// Rate: 10 iters/s needs ~2 VUs
// Rate: 50 iters/s needs ~10 VUs
// Rate: 100 iters/s needs ~20 VUs
Rate Calculation
The iteration rate is spread evenly over the time period:
// With timeUnit: '1s' and target: 100
// = 100 iterations every 1 second
// = 1 iteration every 10ms
// With timeUnit: '1m' and target: 600
// = 600 iterations every 60 seconds
// = 10 iterations per second
Stage Transitions
Transitions between stages are smooth and continuous:
stages: [
{ duration: '1m', target: 50 }, // End at 50 iters/s
{ duration: '2m', target: 100 }, // Start at 50, ramp to 100
]
// No gap between stages - rate smoothly increases from 50 to 100
Common Patterns
Gradual Capacity Test
export const options = {
scenarios: {
capacity: {
executor: 'ramping-arrival-rate',
startRate: 0,
timeUnit: '1s',
preAllocatedVUs: 50,
maxVUs: 500,
stages: [
{ duration: '10m', target: 50 },
{ duration: '10m', target: 100 },
{ duration: '10m', target: 150 },
{ duration: '10m', target: 200 },
{ duration: '10m', target: 250 },
],
gracefulStop: '2m',
},
},
thresholds: {
http_req_duration: ['p(99)<3000'],
dropped_iterations: ['rate<0.01'],
},
};
Spike and Recovery
export const options = {
scenarios: {
spike_test: {
executor: 'ramping-arrival-rate',
startRate: 20,
timeUnit: '1s',
preAllocatedVUs: 50,
maxVUs: 500,
stages: [
{ duration: '2m', target: 20 }, // Baseline
{ duration: '30s', target: 200 }, // Rapid spike
{ duration: '3m', target: 200 }, // Sustain spike
{ duration: '30s', target: 20 }, // Rapid drop
{ duration: '2m', target: 20 }, // Observe recovery
],
},
},
};
Stepped Increases
export const options = {
scenarios: {
stepped: {
executor: 'ramping-arrival-rate',
startRate: 10,
timeUnit: '1s',
preAllocatedVUs: 20,
maxVUs: 200,
stages: [
{ duration: '5m', target: 10 },
{ duration: '0s', target: 25 }, // Instant jump
{ duration: '5m', target: 25 },
{ duration: '0s', target: 50 }, // Instant jump
{ duration: '5m', target: 50 },
{ duration: '0s', target: 100 }, // Instant jump
{ duration: '5m', target: 100 },
],
},
},
};
VU Sizing
Calculate VU requirements for peak rate:
Required VUs ≈ (peak_rate × avg_iteration_duration) / timeUnit
Example:
- Peak rate: 200 iterations/second
- Average iteration: 300ms
- Required VUs ≈ 200 × 0.3 = 60 VUs
Recommended:
- preAllocatedVUs: 60 (for peak)
- maxVUs: 120 (2x safety margin)
Metrics
Key metrics to monitor:
iterations - Total completed iterations
iteration_duration - How long iterations take
dropped_iterations - Iterations dropped (insufficient VUs)
vus - Current active VUs
vus_max - Current allocated VUs (≤ maxVUs)
The current iteration rate can be derived from:
rate = iterations_per_second
Advanced Configuration
Multiple Traffic Types
export const options = {
scenarios: {
read_traffic: {
executor: 'ramping-arrival-rate',
startRate: 50,
timeUnit: '1s',
stages: [
{ duration: '5m', target: 100 },
{ duration: '10m', target: 100 },
{ duration: '5m', target: 50 },
],
preAllocatedVUs: 30,
maxVUs: 100,
exec: 'readTest',
tags: { type: 'read' },
},
write_traffic: {
executor: 'ramping-arrival-rate',
startRate: 10,
timeUnit: '1s',
stages: [
{ duration: '5m', target: 20 },
{ duration: '10m', target: 20 },
{ duration: '5m', target: 10 },
],
preAllocatedVUs: 10,
maxVUs: 50,
exec: 'writeTest',
tags: { type: 'write' },
},
},
};
export function readTest() {
http.get('https://test.k6.io/api/data');
}
export function writeTest() {
http.post('https://test.k6.io/api/data', { data: 'value' });
}
Best Practices
- Size maxVUs generously: Allow 2-3x expected VUs for rate variance
- Start from baseline: Use realistic
startRate from production metrics
- Gradual ramp-up: Give system time to warm up and scale
- Monitor dropped_iterations: Set thresholds to detect insufficient VUs
- Test auto-scaling: Design stages to test scaling triggers
- Use realistic patterns: Model actual production traffic patterns
- Consider iteration variance: Account for varying iteration durations
- Set appropriate timeUnit: Match your SLA/monitoring granularity
Comparison with Other Executors
| Feature | Ramping Arrival Rate | Constant Arrival Rate | Ramping VUs |
|---|
| Rate pattern | Variable over stages | Fixed | N/A (not rate-based) |
| VU count | Dynamic (auto-scaled) | Dynamic (auto-scaled) | Fixed per stage |
| Complexity | High | Medium | Medium |
| Throughput | Varies by stage | Constant | Variable (depends on VUs) |
| Best for | Complex traffic patterns | Steady throughput | User simulation |
Troubleshooting
High Dropped Iterations
// Problem: dropped_iterations increasing
// Solution: Increase maxVUs
{
maxVUs: 500, // Increase from 200
}
VU Churn (Frequent Allocation)
// Problem: VUs constantly being allocated/deallocated
// Solution: Increase preAllocatedVUs to peak needs
{
preAllocatedVUs: 100, // Increase from 50
}
Rate Not Achieved
Check:
maxVUs sufficient for iteration duration × rate
- Backend can handle the load (not throttling)
- Network bandwidth adequate
dropped_iterations metric for evidence
See Also