Module 1: Why Load And Performance Testing

4. The types: smoke, load, stress, spike, soak

Overview

"Load test" isn't a single thing. Depending on which question you want to answer, you give the system a different shape of traffic, and each shape has a name. There are five that form the industry's standard vocabulary, and knowing which to use is half of designing a useful test. Smoke: does the system even work under minimal load? Load: does it hold the traffic you expect on a normal day? Stress: where's its limit —the breaking point—? Spike: does it survive a sudden, brutal traffic peak? Soak (or endurance): does it degrade when subjected to sustained load for hours —memory leaks, connections that aren't released—? Each answers a question the others don't, and each is a different load profile: a way of ramping up, sustaining, and ramping down the number of users over time. In this lesson we walk through them one by one, with their question, their shape, and what they're for —and we establish the golden rule: you always start with the smoke.

Connection to the module: this lesson connects the three questions from lesson 3 with the concrete tools. The "breaking point" question is answered with a stress test; the "expected capacity" one with a load test; and two new questions appear (sudden peaks, degradation over time) brought by the spike and the soak. Here we describe the shape of each type at a conceptual level; giving it that shape with code —k6's stages, ramps, executors— is the whole of module 4. Think of this lesson as the catalog: what exists and what for, before learning to build each one.

Five ways to test a bridge

Let's go back to the bridge engineer from lesson 2, because their tests correspond one to one with the five types.

Before anything, they run a smoke test: they send a single car to cross, slowly. It doesn't aim to stress anything; it aims to confirm the bridge is open, that there's no obvious hole, that you can get across. If the bridge falls with one car, there's no point bringing the trucks. That's the smoke test.

Then, the normal load test: they put the traffic of a typical peak hour on the bridge —the number of vehicles it will actually bear each day— and measure how much it flexes. Does it meet the expected traffic without over-deforming? That's the load test.

Next, the stress test: they keep adding trucks, more and more, well beyond normal traffic, until finding the point where the structure starts to yield. They don't expect to cross that point in real life; they want to know it, to know how much margin they have. That's the stress test.

Then, the spike test: instead of raising the weight little by little, they drop fifty trucks at once in two seconds —as if a traffic light released a whole line at once— and watch whether the bridge absorbs the blow or feels the strain. That's the spike test.

And finally, the endurance test: they put a moderate load, that of normal traffic, and leave it there twenty-four hours straight, watching whether something works loose over time —a bolt vibrating loose, a joint fatiguing— that would never appear in a ten-minute test. That's the soak test.

A serious engineer runs all five, because each reveals a failure the others wouldn't see. Your API is the same.

The five types, one by one

Smoke: does it work under minimal load?

The smoke test uses a tiny load —one or a few users, a few seconds— and its only goal is to confirm the system responds and isn't broken before spending time on big tests. Its name comes from electronics: you plug in the device and see if it "smokes." It doesn't measure performance seriously; it verifies the test script is correct and the API is alive and returns what's expected.

What to expect — a smoke against Reservo is a few requests confirming the API responds and returns the correct anchor number. Real output from the generator with 5 requests and 1 concurrent:

$ python3.14 load_generator.py http://127.0.0.1:PORT 5 1
requests ............ 5 (concurrency 1)
all returned ........ price_cents=7500 (correct: True)
total duration ...... 0.009 s
throughput .......... 554.4 req/s
latency min ......... 0.34 ms
latency avg ......... 1.73 ms
latency max ......... 7.09 ms
latency p95 ......... 7.09 ms

Don't look at the performance numbers (with 5 requests they mean nothing); look at correct: True. The smoke confirmed two things: the API is alive and returns the expected 7500. Golden rule: you always start with the smoke. If your smoke fails, no bigger test makes sense —you fix the script or the API first—. Running a 1000-VU stress when not even one user gets a correct response is throwing away time.

Load: does it hold the expected load?

The load test is the default type, the one people picture when they say "load test." It subjects the system to the load you expect in normal operation or a reasonable, predictable peak —for example, "300 concurrent users, which is our typical Tuesday afternoon"— and verifies it meets your latency and error targets under that load. It answers: does the system do its job, on time, with the real demand? Its typical profile is a ramp up, a sustained stretch at the target load, and a ramp down. It's the test that confirms you're ready for a normal day.

Stress: where's the limit?

The stress test pushes the system beyond its expected load, raising concurrency steadily until something yields: latency spikes non-linearly or the error rate stops being zero. It answers the third question from lesson 3: where's the breaking point? Its profile is a ramp that keeps rising in steps, higher and higher, watching at which step the p95 gets out of control. You don't expect to operate there; you want to know your limit to know how much margin you have and how the system behaves when saturated (does it degrade gracefully, rejecting requests cleanly, or collapse with ugly errors?).

Spike: does it survive a sudden peak?

The spike test is a stress with one crucial difference: the load doesn't rise gradually, but all at once. It goes from almost nothing to a very high load in seconds, holds for a moment, and cuts off. It simulates real, brutal events: a campaign going live, a viral mention, a ticket sale opening, a Super Bowl ad. It answers: does the system absorb a sudden blow or fall over? —and also does it recover when the peak passes, or stay down?—. A system can hold 1000 users if it reaches them in ten minutes (load/stress) and still fall over if those 1000 arrive in ten seconds (spike), because it had no time to scale resources or drain queues.

Soak: does it degrade with hours of sustained load?

The soak test (or endurance) applies a moderate load —usually the expected one, not the extreme— but for a long time: hours, sometimes a whole day. Its goal isn't the peak but the duration, because there are failures that only manifest over time: memory leaks (the used memory grows and grows until the process dies), database connections that aren't returned to the pool and get exhausted, log files that fill the disk, caches that grow without limit. It answers: does the system stay stable under sustained load, or slowly degrade until it fails? A system can pass a ten-minute load test with flying colors and die after three hours from a leak that was invisible in ten minutes.

The summary table

TypeQuestion it answersShape of the loadWhen you use it
SmokeDoes it work under minimal load?Tiny (1-2 users, seconds)Always first; validate script and basic health
LoadDoes it hold the expected load?Ramp → sustain at target load → ramp downVerify you meet your targets on a normal day
StressWhere's the breaking point?Increasing ramp in steps, beyond normalKnow your limit and your margin
SpikeDoes it survive a sudden peak?Abrupt jump to high load, brief, and cutPrepare for campaigns, virals, sale openings
SoakDoes it degrade with hours of load?Moderate sustained load for hoursHunt memory/connection leaks and slow degradation

Read it as a decision tree: if you never tested, smoke. If you want to know whether you hold your real traffic, load. If you want to know your ceiling, stress. If you fear a sudden peak, spike. If you fear something rots over time, soak. Most teams live with smoke + load as routine, and bring out stress, spike, and soak when the question calls for it.

One target, five tests

Notice that all five types hit the same API (Reservo, or yours) and use the same metrics (p95 latency, throughput, error rate, from lesson 3). The only thing that changes between them is the load profile: how many users, how they ramp up, how long they sustain, how long the whole thing lasts. A smoke and a soak can use the very same k6 script (the same function that does /quote); what distinguishes them is the stages/duration/vus configuration —the shape—. That's why, when in module 4 you learn to write load profiles (ramps, steps, spikes), you'll be learning to build any of these five types by just changing a few numbers. This lesson's vocabulary is the catalog; module 4 is the factory.

Common mistakes

Skipping the smoke and launching straight into a thousand-user stress. What happens: someone configures a huge test, runs it for half an hour, and discovers at the end that the script had a bug (the URL was wrong, the JSON body malformed) and all requests failed —not because of the system, because of the test—. Why it happens: the excitement of "testing for real" skips the boring step. How to detect it: if your first test of a new script is big, you're missing the smoke. How to fix it: always run a 1-2 user smoke first; confirm the script works and the API responds correctly, and only then scale.

Confusing spike with stress because "both use a lot of load." What happens: someone wants to test a viral campaign (a sudden peak) but configures a slow, gradual ramp, and concludes "it holds up" —when in real life the traffic would have arrived all at once and knocked it down—. Why it happens: both reach high load, and the difference (gradual vs sudden) seems like a detail. But how the load arrives is exactly what the spike tests. How to detect it: if your "peak" test rises over minutes instead of seconds, it's not a spike. How to fix it: to simulate a peak, the load must jump almost instantly; it's a different profile (module 4).

Believing a 10-minute load test rules out memory leaks. What happens: the load test passes perfectly, the system is declared stable, and in production the process dies every six hours from a leak. Why it happens: a slow leak is invisible in ten minutes; it only emerges over time. How to detect it: if your concern is "does it degrade with prolonged use?" and your test lasts minutes, you're looking at the wrong phenomenon. How to fix it: that's hunted by a soak test of hours, watching memory/connection usage over time, not the latency of a brief while.

Exercises

Exercise 1 — Choose the type. For each goal, say which test type (smoke, load, stress, spike, soak) meets it. (a) "Before the big test, confirm my k6 script and the API work." (b) "Know beyond how many concurrent users Reservo's latency gets out of control." (c) "Check the server doesn't fall over if we're mentioned on the news tomorrow and a flood arrives in seconds." (d) "Verify Reservo holds the 300 concurrent of a normal Tuesday while meeting the p95." (e) "Detect whether the process leaks memory after eight hours of continuous traffic."

See solution
  • (a) Smoke. Validate script + basic health with minimal load, before scaling.
  • (b) Stress. Look for the breaking point by raising the load until latency yields.
  • (c) Spike. A sudden flood in seconds: the abrupt-jump profile.
  • (d) Load. The expected load of normal operation, verifying the targets.
  • (e) Soak. A memory leak that only appears with sustained load over hours.

Exercise 2 — Same script, different shape. Explain in two or three sentences why a smoke test and a soak test can use exactly the same k6 script (the same function that hits /quote) and still be different tests. What's the only thing that changes between them?

See solution

What each request does (call /quote, verify the 7500) is identical in both: the same VU function, the same endpoint, the same metric. The only thing that changes is the load profile —the configuration of how many users and for how long—: the smoke uses 1-2 users for seconds; the soak uses a moderate load for hours. The shape of the load (number of VUs and duration), not the work of each request, is what turns the same script into one test type or another. (Building those shapes is module 4.)

Exercise 3 — The order of a campaign. Your team is about to launch a Black Friday promotion on Reservo. Design, in order, what sequence of test types you'd run before launch and why each one, in one sentence.

See solution

A reasonable sequence:

  1. Smoke — first of all: confirm the script and API respond correctly under minimal load; if this fails, nothing else makes sense.
  2. Load — verify Reservo holds the expected Black Friday load (e.g. 1000 concurrent) while meeting the p95 and error target.
  3. Stress — push beyond the expected to know the breaking point and how much margin we have if the estimate falls short.
  4. Spike — simulate the sudden blow of the minute the promotion goes live, when everyone enters at once, and see if the system absorbs and recovers.
  5. Soak (if the promo lasts many hours) — sustain the load for hours to rule out memory leaks that would knock the system down mid-event.

What matters is the pattern: you start with the smoke, move up to the load, and bring out stress/spike/soak according to the concrete risks of the event.

Summary and next step

In this lesson you walked through the five load test types and the question each answers: smoke (does it work under minimal load? — always first), load (does it hold the expected load?), stress (where's the breaking point?), spike (does it survive a sudden peak?), and soak (does it degrade with hours of sustained load?). You saw them with the bridge engineer —a test car, normal traffic, more and more trucks, a sudden blow, twenty-four hours straight— and confirmed the golden rule: you always start with the smoke, like the 5-request generator that only confirmed Reservo is alive and returns 7500.

The idea to take from the lesson is that all five hit the same API with the same metrics; the only thing that changes is the shape of the load —how many users, how they ramp up, how long they last—. That load profile is what turns the same script into one test type or another.

Before moving on you should be able to: name the five types and their question; explain why the smoke goes first; distinguish a stress (gradual rise to the limit) from a spike (sudden jump); and say what a soak hunts that a ten-minute load wouldn't see.

What comes next is meeting the tool these tests are built with in the industry. In lesson 5 comes k6: what it is, why its scripts are written in JavaScript but run on their own runtime (not Node), and what that means for how they're written and why in this guide they're presented as content.

Resources