Open vs closed workload models
The workload model is one of the most consequential choices in a load test design. Get it right and your test accurately represents real traffic. Get it wrong and your results can be systematically misleading — either hiding or exaggerating the system’s capacity problems.
The two models
Section titled “The two models”Closed workload (fixed VU count)
Section titled “Closed workload (fixed VU count)”In a closed workload model, a fixed pool of virtual users runs continuously. Each VU completes a request, optionally waits (think time), and immediately starts the next request. The total number of in-flight requests is bounded by the VU count.
The key property: the system’s response time affects throughput. If the system slows down, each VU spends longer waiting for a response, and throughput drops. The test “adapts” to the system.
Closed models are the default in Taurus and JMeter. They work well when:
- You want to simulate a fixed number of concurrent users, each interacting steadily with the system (think a logged-in user making requests in a session).
- You expect the system to be the bottleneck (response times > think time).
- You are doing a baseline comparison where you want consistent VU count across runs.
Open workload (arrival rate)
Section titled “Open workload (arrival rate)”In an open workload model, requests arrive at a fixed rate regardless of how fast the system responds. New requests do not wait for existing ones to finish. The number of in-flight requests can grow without bound if the system is slow.
The key property: throughput is fixed; concurrency grows as the system slows. This is how most real-world traffic works — users arrive at the site on their own schedule regardless of how slow the server is. When servers slow, requests queue; they don’t politely wait until the server is fast again.
Open models are available in Taurus with the throughput execution key, in k6 with
constant-arrival-rate, and in JMeter with the Throughput Shaping Timer.
Which model does real traffic follow?
Section titled “Which model does real traffic follow?”Real internet traffic is almost always open. Users arrive independently — they don’t pause and wait for your server to catch up. A sudden surge (a product launch, a viral link) adds new arrivals regardless of how the system is performing.
This makes open models more representative for externally-facing systems. Closed models tend to underestimate the impact of latency degradation because they naturally back off when the system slows (fewer requests per second when each VU is waiting longer).
When to use each model in MaxoPerf
Section titled “When to use each model in MaxoPerf”| Scenario | Recommended model | Reason |
|---|---|---|
| API performance baseline | Closed (fixed VUs) | Easy to compare across runs; VU count is a stable parameter. |
| Capacity / breakpoint test | Open (arrival rate) | Accurately models real traffic surge behavior; concurrency grows realistically. |
| Background job simulation | Closed | Jobs run at fixed concurrency; think time = processing gap. |
| Web storefront peak load | Open | Real users arrive independently at a rate driven by traffic patterns, not the server. |
| CI regression test (fast) | Closed (low VU count) | Speed and simplicity matter more than realism for regression checks. |
Configuring an open workload in Taurus
Section titled “Configuring an open workload in Taurus”execution: - concurrency: 50 throughput: 200 # target RPS (arrival rate) hold-for: 10m scenario: api-loadThe throughput key sets the target arrival rate in RPS. Taurus will spawn up to concurrency
VUs to sustain that rate. If the system cannot serve 200 RPS with 50 VUs, the actual measured
RPS in MaxoPerf will be lower — and the gap reveals the shortfall.
Configuring a closed workload in Taurus
Section titled “Configuring a closed workload in Taurus”execution: - concurrency: 100 hold-for: 10m ramp-up: 2m scenario: api-loadNo throughput key: Taurus runs exactly 100 VUs continuously. The measured RPS is whatever the
system can serve at 100 concurrent VUs.
Reading results from each model
Section titled “Reading results from each model”From a closed workload run: read RPS as the maximum throughput at that concurrency. If RPS is lower than you expected from 100 VUs, the system is slower than your design assumed.
From an open workload run: read concurrency (inferred from rising latency) as a sign of queue buildup. If you asked for 200 RPS and saw only 150 RPS with rising p99, the system is at its effective ceiling and the queue is growing.
Do / don’t
Section titled “Do / don’t”| Do | Don’t |
|---|---|
| Use open workload when modeling real internet traffic with an external audience. | Default to closed workload for every test without considering whether fixed-VU behavior matches real traffic. |
| Verify that the target RPS in an open-model run is actually achieved — the gap is meaningful. | Interpret throughput from a closed-model run as the system’s absolute capacity — it only tells you capacity at that VU count and think time. |
| Document which model you used in test notes so comparisons are like-for-like. | Compare a closed-model baseline with an open-model run — the results are not directly comparable. |
Where to go next
Section titled “Where to go next”- Virtual users and concurrency — the difference between VU count and the concurrency that results from it.
- Ramp-up, think time, and pacing — shaping the load profile within either model.
- How much load do you need? — translating traffic data into a workload configuration.
- RPS-controlled throughput test — a cookbook recipe for the open workload pattern.