CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/slo-load-test-plan

Turns a service's SLOs and endpoint traffic mix into a named scenario matrix: one scenario per SLO boundary condition, a load profile (smoke, average-load, stress, soak, spike, breakpoint) per scenario, an open or closed workload injection model, a threshold expression derived from the SLO the scenario guards, and an error-budget calculation that sets the soak run's failure allowance. Stays runner-agnostic and fixes the pass/fail line before any tool is configured. Use when an SLO document and an endpoint list both exist but nobody has decided which load runs to make, what shape of load each carries, or what number would count as a failure.

75

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

runners.mdreferences/

Runner executors and a worked plan

Reference material for slo-load-test-plan: how the open/closed distinction appears in the two most common runners, and a full worked example turning a set of SLOs into a scenario matrix. The plan itself stays runner-agnostic; this file is where the runner-specific names and the end-to-end example live.

Open vs closed in the two most common runners

RunnerOpen modelClosed model
k6constant-arrival-rate, ramping-arrival-rate executors (k6 open and closed models)constant-vus and the other non-arrival-rate executors (k6 open and closed models)
GatlinginjectOpen with atOnceUsers, rampUsers, constantUsersPerSec, rampUsersPerSec, stressPeakUsers (Gatling injection)injectClosed with constantConcurrentUsers, rampConcurrentUsers, incrementConcurrentUsers (Gatling injection)

Note the trap in the Gatling column: rampUsers and atOnceUsers are open-model blocks that inject a number of users over a window, while the closed-model blocks are the *ConcurrentUsers family, which hold a level of concurrency in the system (Gatling injection). "Users" in a profile name does not mean closed.

Worked example

Input: a checkout service. SLOs are p95 < 300 ms on POST /api/checkout at peak, p95 < 100 ms on GET /api/orders at average, error rate < 0.1% under a 3x spike, and 99.9% availability over four weeks. Traffic mix is GET /api/orders 60%, POST /api/checkout 20%, everything else 20%. Peak is 300 RPS, average 100 RPS, with a 3x spike on sale days.

Resulting scenario matrix:

ScenarioSLO governedProfileInjectionTargetDuration
smoke-mixnone (gate)SmokeOpen1 arrival/sec60 s
orders-latency-averagep95 < 100 ms on ordersAverage-loadOpen100 arrivals/sec30 min
checkout-latency-peakp95 < 300 ms on checkoutStressOpen300 arrivals/sec30 min
spike-error-budgeterror rate < 0.1%SpikeOpen900 arrivals/sec3 min
soak-availability99.9% over four weeksSoakOpen300 arrivals/sec4 h
capacity-ceilingnone (capacity finding)BreakpointOpenramp to failureuntil failure

Thresholds:

ScenarioExpressionScopeAbortTraceable to
orders-latency-averagep(95)<100orders tagnoorders latency SLO
checkout-latency-peakp(95)<300checkout tagnocheckout latency SLO
spike-error-budgetrate<0.001allno (recovery is the measurement)spike error-rate SLO
soak-availabilityrate<0.001allyes, delayAbortEval: '10s'99.9% availability, pro-rata over 4.32M requests = 4,320 failures
capacity-ceilingnonen/an/acapacity finding, not an SLO

Every load number is open-model arrivals per second, because every SLO here is stated per request rather than per session.

references

SKILL.md

tile.json