Skip to content

Load testing: test types and open vs closed models

Pick the test by the question, and the model by how real users arrive.

Predict first

Before you read: predict

ExamHall's team load-tests the autosave endpoint on staging before ECON-201's sitting:

The staging server answers one request at a time, in arrival order, 10 ms each. From 5 s to 7 s into the run it freezes (a stop-the-world pause) and answers nothing; then it carries on.

What does the k6 report show for http_req_duration (percentiles by nearest rank)?

Code for this question
// autosave-load.jsimport http from 'k6/http';import { sleep } from 'k6'; export const options = { scenarios: { autosave: { executor: 'constant-vus', vus: 1, duration: '10s' } } }; export default function () {  http.post('https://staging.examhall.test/api/autosave');  sleep(0.03);}
Pick one

The 30-second version

Six test types ask six questions: smoke, average-load, stress, soak, spike and breakpoint. The load model decides whether the answer is true. In a closed model each virtual user waits for its answer, so a slow server gets less load and the report records few slow samples. An open model starts iterations on schedule, as real users arrive.

Pick the test by the question, and the model by how real users arrive.

How it works

Step 1 of 10

Smoke. A smoke test runs minimal load, a few virtual users (VUs), to validate that the script works and the system performs adequately.

Analogy: A vaccination clinic's dry run before flu-jab day

At the clinic In a load test
a few staff play patients: each walks the route, then rejoins the queue at the door a closed model (step 4)
the registration laptop freezes for ten minutes: the staff stand in line, nobody new comes in, and the stopwatch sheet shows a few long waits fewer requests, fewer slow samples (steps 5–6)
on the day, patients come at their booking times whatever the queue an open model (step 7)
the booking sheet sets when each patient walks in, not when each station sees them iterations, not requests, on schedule (step 8)

In real terms: before reading a report's percentiles, ask whether the generator kept sending while the system was slow.

Breaks down when: real patients give up and leave a long queue; an arrival-rate test keeps arriving however long the queue grows.

Contrasting case: a clinic that never has a queue. With no freeze and no slowdown, both rehearsals see the same short waits, and the model does not matter.

Examples, run for real

4.1 ExamHall EXH-4230: the autosave test, as shipped and after MR !4530

EXH-4230: before ECON-201, the autosave load test reported a p99 of 10 ms; on the morning of the sitting, a one-second pause on the autosave server left candidates waiting nearly a second. The test as shipped:

// autosave-load.js (as shipped)
export const options = { scenarios: { autosave: { executor: 'constant-vus', vus: 1, duration: '10s' } } };
export default function () {
  http.post('https://staging.examhall.test/api/autosave');
}

MR !4530 changes only how autosaves are offered: one starts every 20 ms for the same 10 s, whatever the answers, as candidates send them. Both ran against staging (one request at a time, 10 ms each) with a freeze from 5 s to 6 s:

4.1 EXH-4230 as shipped (1 VU waiting for each answer): requests 900 · started during the freeze 1 · p99 10 ms · slower than 100 ms 1
4.1 MR !4530 (one every 20 ms): requests 500 · started during the freeze 50 · p99 960 ms · slower than 100 ms 91

As shipped, the VU sent 900 requests, more than the MR's 500, yet the freeze left one slow sample (steps 5–6, 9). On the MR's schedule, 50 requests arrived during the freeze and more queued behind them, so the p99 shows the wait candidates saw (step 7).

4.2 What the MR does not decide

Which rate to offer comes from production's own traffic, and which further test types the sitting needs is a separate choice (step 10). Why a backlog drains at the server's own rate belongs to scale-littles-law-capacity.

Try it

Answer first, then check. Nothing is saved.

Question 1 of 7

A chat team load-tests message sending on staging:

Staging's message API has 8 workers, each taking 10 ms per message. Production's evening peak is 400 messages a second, and once a night the API freezes for 1.5 s. In the next staging run, the API freezes for 1.5 s, 30 s into the run, and the team wants the test to start at least 400 messages in every second of the run, the frozen ones included. An arrival-rate scenario would keep duration: '60s' and take timeUnit: '1s' and preAllocatedVUs: 1000.

Which change does it?

Code for this question
// send-load.jsimport http from 'k6/http';import { sleep } from 'k6'; export const options = { scenarios: { send: { executor: 'constant-vus', vus: 40, duration: '60s' } } }; export default function () {  http.post('https://staging.chat.test/api/messages');  sleep(0.09);}
Pick one

Question 2 of 7

A chat team load-tests opening the inbox on staging:

Staging's inbox API has 10 workers; each request takes one worker 50 ms, and nothing freezes.

How many samples does the report's http_req_duration hold?

Code for this question
// inbox-load.jsimport http from 'k6/http';import { sleep } from 'k6'; export const options = { scenarios: { inbox: { executor: 'constant-vus', vus: 5, duration: '10s' } } }; export default function () {  http.get('https://staging.chat.test/api/inbox');  http.get('https://staging.chat.test/api/inbox/unread');  sleep(0.4);}
Pick one

Question 3 of 7

A chat team load-tests opening a room: each iteration loads the room's history, then posts a read receipt:

The iterations are numbered from 0 in the order they start. Staging answers one request at a time, in arrival order, 10 ms each, and freezes from 1,000 ms to 1,500 ms of the run.

In what order does the test send these four requests?

Code for this question
// open-room-load.jsimport http from 'k6/http'; export const options = { scenarios: { open: { executor: 'constant-arrival-rate', rate: 10, timeUnit: '1s', duration: '3s', preAllocatedVUs: 50 } } }; export default function () {  http.get('https://staging.chat.test/api/rooms/7/history');  http.post('https://staging.chat.test/api/rooms/7/read');}

Your order

  1. 1empty
  2. 2empty
  3. 3empty
  4. 4empty

Tap the lines in the order you expect.

Question 4 of 7

A chat company's WebSocket gateway keeps a small record for every connection it has served and never frees it. At a normal evening's traffic it slows down after about three hours. Before the next release the team wants a load test that would have caught it.

Which test is built for that?

Pick one

Question 5 of 7

In a mock interview you are asked: "What would you load-test before New Year's Eve?" Three candidates each answer with a test of message sending, run against staging, which has 20 workers at 10 ms a message, like production. Each runs this function in a constant-arrival-rate scenario with timeUnit: '1s' and preAllocatedVUs: 20000:

The interviewer follows up: "At midnight, 2,500 messages a second arrive for 30 s.

Whose test reports the p99 your users will see that night?

Code for this question
export default function () {  http.post('https://staging.chat.test/api/messages');}
Pick one

Question 6 of 7

On Monday a streaming team rewrote its k6 script for the new playback journey; nobody has run it yet. Tonight the shared load rig is booked for a one-hour stress test of playback.

What should the team run first?

Pick one

Question 7 of 7

A box office will put a waiting room in front of its seat-hold service for the summer on-sale, admitting fans at a fixed rate. To set that rate, the team needs the request rate at which seat holds start failing.

Which test gives that number?

Pick one

Go deeper

Pro tips
  1. Read the request count before the percentiles. Compare a closed test's requests with the rate you meant to offer; if it fell while the system was slow, its percentiles under-record the slow part. When: any load-test report you sign off (steps 5–6).
  2. Give an arrival-rate scenario enough VUs for its slowest moment. It needs about rate × the longest iteration you expect in flight at once (scale-littles-law-capacity step 1). When: setting preAllocatedVUs (step 7).
tip 2 MR !4530: most VUs busy at once 51 · rate 50 a second × longest iteration 1,010 ms = 51 · preAllocatedVUs 100
Source
  • Grafana k6 docs, "Load test types" (the row's first source): https://grafana.com/docs/k6/latest/testing-guides/test-types/ · fetched 2026-10-15 with curl. "Start with smoke tests, then progress to higher loads and longer durations." (step 1); "Average-load test assess how your system performs under expected normal conditions." and "Stress tests assess how a system performs at its limits when load exceeds the expected average." (step 2); "Soak tests assess the reliability and performance of your system over extended periods.", "Spike tests validate the behavior and survival of your system in cases of sudden, short, and massive increases in activity." and "Breakpoint tests gradually increase load to identify the capacity limits of the system." (step 3); "k6 can model load by either number of VUs or by number of iterations per second" (step 10). Valid as of 2026-10-15.
  • Grafana k6 docs, "Open and closed models" (the row's second source): https://grafana.com/docs/k6/latest/using-k6/scenarios/concepts/open-vs-closed/ · fetched 2026-10-15. Teaching (steps 4–9) and the rules the model implements: "in the closed model, VU iterations start only when the last iteration finishes." (step 4, constant-vus); "Slower response times means longer iterations and a lower arrival rate of new iterations" and "In some testing literature, this problem is known as coordinated omission." (steps 5–6); "In the open model, on the other hand, VUs arrive independently of iteration completion." and "k6 implements the open model with two arrival rate executors: constant-arrival-rate and ramping-arrival-rate" (step 7). No key is cited from this page: every key it informs is executed in the model. Valid as of 2026-10-15.

Checked against the tools and docs as of 2026-10-15.