Works with the AI Agents you already use

    Claude CodeClaude CodeCursorCursorCodex CLICodex CLIMuseMuseDotsDots+22 more

    Stress Testing — Load, Spike, Soak & Breakpoint Plans

    1

    Plans and interprets load tests (smoke, stress, spike, soak, breakpoint) with realistic workloads and SLO thresholds.

    Free

    Security scanned
    Stress Testing — Load, Spike, Soak & Breakpoint Plans

    Stress Testing — Load, Spike, Soak & Breakpoint Plans

    Example session with this skill installed

    Please plan a load test for our checkout API before Black Friday. We use k6.

    • Target: staging, https://staging-api.shopfictional.dev
    • Endpoints: GET /products?page=N, GET /products/:id, POST /cart/items, POST /checkout
    • From our APM: normal peak hour is about 120 requests/second across these endpoints. We expect roughly 2x on Black Friday.
    • SLO: p95 under 400 ms, error rate under 1%.

    Don't run anything yet. I want the plan and the script first.

    • Read your context and instructions
    • Compiled the stress testing

    Summary

    Nothing has been run. This is the plan, the k6 script, and the pass/fail criteria for you to review. The goal is to answer one question: does checkout hold the Black Friday peak on staging? Given your numbers, that means a

    smoke run, an

    average-load baseline at 120 req/s, and a

    stress run at 240 req/s, in that order. A

    spike run is optional; it needs a spike level from you. All load uses the

    open model (arrival rate), because web traffic keeps arriving whether or not the API is slow.

    Confirm before any run

    Target and environment: https://staging-api.shopfictional.dev. Is staging shared with other teams tonight? A stress run at 240 req/s will degrade it for anyone else using it.
    2. Payments: POST /checkout must hit a payment sandbox, not a real provider. Please confirm.
    3.

    Data volume: how close are staging's product, user, and order tables to production size? Problems that hide at 1k rows often show up at 1M. This plan writes down whatever gap exists as a limit on the conclusions.
    4.

    Traffic mix: I assumed 60% browse list / 25% product detail / 10% add to cart / 5% checkout. That is a placeholder. Replace it with the endpoint split from your APM.
    5.

    Spike level: if you want a spike test, give me the surge you're planning for (for example, the expected traffic when the campaign email goes out).
    6.

    Load generator: run it from a machine with headroom, in the same location for every run, and keep it the same for future baseline comparisons.

    Plan

    RunQuestionProfilePass/fail
    SmokeDo the script and the environment work?2 VUs, 1 minAll checks pass, 0 errors
    Average-loadDoes it handle a normal peak hour?Ramp to 120 req/s over 5 min, hold 30 min, ramp down 5 minp95 < 400 ms, errors < 1%
    StressDoes it handle 2x?Ramp to 240 req/s over 10 min, hold 20 min, ramp down 5 minSame thresholds
    Spike (optional)Does it survive a surge, and recover?120 → SPIKE_RPS in 30 s, hold 2 min, back to 120Same thresholds, plus a return to baseline latency within minutes

    Stress runs only if average-load passes. If the system fails at normal load, a 2x test produces noise.

    Script: checkout-load.js

    import http from 'k6/http';
    import { check } from 'k6';
    import { SharedArray } from 'k6/data';
    
    const BASE = __ENV.BASE_URL;
    const PROFILE = __ENV.PROFILE || 'smoke';
    
    // Parameterized data: varied products and users, so caches don't fake the result.
    const products = new SharedArray('products', () => JSON.parse(open('./data/products.json')));
    const users = new SharedArray('users', () => JSON.parse(open('./data/users.json'))); // staging test accounts + tokens
    
    const arrival = (stages) => ({
      executor: 'ramping-arrival-rate',  // open model
      startRate: 0,
      timeUnit: '1s',
      preAllocatedVUs: 200,
      maxVUs: 1000,
      stages,
    });
    
    const PROFILES = {
      smoke: { executor: 'constant-vus', vus: 2, duration: '1m' },
      average: arrival([
        { target: 120, duration: '5m' },
        { target: 120, duration: '30m' },
        { target: 0, duration: '5m' },
      ]),
      stress: arrival([
        { target: 240, duration: '10m' },
        { target: 240, duration: '20m' },
        { target: 0, duration: '5m' },
      ]),
      spike: arrival([
        { target: 120, duration: '2m' },
        { target: Number(__ENV.SPIKE_RPS), duration: '30s' },
        { target: Number(__ENV.SPIKE_RPS), duration: '2m' },
        { target: 120, duration: '30s' },
        { target: 120, duration: '5m' },  // recovery window
      ]),
    };
    
    export const options = {
      scenarios: { [PROFILE]: PROFILES[PROFILE] },
      thresholds: {
        // SLO, measured on successful responses so fast errors can't flatter latency
        'http_req_duration{expected_response:true}': ['p(95)<400'],
        http_req_failed: ['rate<0.01'],
        // per-flow visibility: checkout must meet the SLO on its own
        'http_req_duration{flow:checkout}': ['p(95)<400'],
        // generator health: dropped iterations mean the generator couldn't keep the rate
        dropped_iterations: ['count<1'],
      },
    };
    
    const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
    
    export default function () {
      const r = Math.random();
      const user = pick(users);
      const auth = { headers: { Authorization: `Bearer ${user.token}`, 'Content-Type': 'application/json' } };
    
      if (r < 0.60) {
        const page = 1 + Math.floor(Math.random() * 20);
        const res = http.get(`${BASE}/products?page=${page}`, { tags: { name: 'GET /products', flow: 'browse' } });
        check(res, { 'list 200': (x) => x.status === 200 });
      } else if (r < 0.85) {
        const res = http.get(`${BASE}/products/${pick(products).id}`, { tags: { name: 'GET /products/:id', flow: 'detail' } });
        check(res, { 'detail 200': (x) => x.status === 200 });
      } else if (r < 0.95) {
        const res = http.post(`${BASE}/cart/items`, JSON.stringify({ productId: pick(products).id, qty: 1 }),
          { ...auth, tags: { name: 'POST /cart/items', flow: 'cart' } });
        check(res, { 'cart 2xx': (x) => x.status >= 200 && x.status < 300 });
      } else {
        const add = http.post(`${BASE}/cart/items`, JSON.stringify({ productId: pick(products).id, qty: 1 }),
          { ...auth, tags: { name: 'POST /cart/items', flow: 'checkout' } });
        // Don't fire a dependent request after a failure; under load, errors are expected.
        if (!check(add, { 'checkout: cart 2xx': (x) => x.status >= 200 && x.status < 300 })) return;
        const res = http.post(`${BASE}/checkout`, JSON.stringify({ paymentMethod: 'sandbox_test_card' }),
          { ...auth, tags: { name: 'POST /checkout', flow: 'checkout' } });
        check(res, { 'checkout 2xx': (x) => x.status >= 200 && x.status < 300 });
      }
    }
    

    Each iteration is one request, except checkout, which makes two. So the configured arrival rate approximates requests per second, and runs slightly above it because of the checkout share. data/products.json and data/users.json must hold real staging IDs and test-account tokens.

    Commands (not executed)

    k6 run -e BASE_URL=https://staging-api.shopfictional.dev -e PROFILE=smoke   checkout-load.js
    k6 run -e BASE_URL=https://staging-api.shopfictional.dev -e PROFILE=average checkout-load.js
    k6 run -e BASE_URL=https://staging-api.shopfictional.dev -e PROFILE=stress  checkout-load.js
    k6 run -e BASE_URL=https://staging-api.shopfictional.dev -e PROFILE=spike -e SPIKE_RPS=<agreed> checkout-load.js
    

    k6 exits non-zero when a threshold fails, so the same commands work as a CI gate. Keep a kill switch ready (Ctrl+C, or stopping the generator host) for every run beyond smoke.

    How to read the results

    Report each threshold next to its measured value (for example, "p95 X ms vs 400 ms"), never "seemed fine". Paste the k6 summary, trimmed to the relevant lines.

    Read p50/p90/p95/p99 and the max, not the average. A p50–p99 gap that widens as load climbs points to queuing: pools, locks, GC, or a slow downstream service.

    Read errors and latency together. Thresholds are measured on expected_response:true because a 5 ms 500 would otherwise make latency look better.

    Watch for a throughput plateau. If req/s stays flat while the configured rate keeps rising, the system has saturated. Find the timestamp and check CPU, memory, DB connections in use, queue depth, and payment-sandbox latency. The first resource to saturate is the finding.

    Classify the failure mode: graceful (429s, shedding, queuing with backpressure) or catastrophic (timeout cascades, OOM, restarts). Catastrophic failure at 240 req/s is a fix before Black Friday, not a note.

    Check generator health. If dropped_iterations is above zero or the generator's CPU or network was maxed, the run is inconclusive. Discard it and rerun with more capacity; don't report its numbers.

    Measure recovery after stress and spike: latency should return to baseline and queues should drain within minutes.

    Next steps

    1. Answer the six confirmation questions above, especially the real traffic mix and whether staging is shared.
    2. Fill data/products.json and data/users.json from staging.
    3. Run smoke and share the output; I'll check the script's behavior before any heavy run.
    4. After average-load, record the baseline (thresholds, measured percentiles, environment, generator location) in learnings/. That baseline is what the stress run, and every future run, gets compared against.

    Connects securely to your tools. The creator never sees your data.

    About this skill

    Stress Testing helps you answer "how much traffic can this handle?" with evidence. There is no single "stress test": the skill distinguishes six test types, each answering one question. It then models realistic load and judges results by percentiles against an SLO declared before any load is generated.

    The six types:

    • Smoke: does it work at all?
    • Average-load: does it handle normal traffic?
    • Stress: does it handle the peak?
    • Spike: does it survive a sudden surge?
    • Breakpoint: where and how does it break?
    • Soak: does it degrade over hours?

    The order is fixed: smoke first, then average-load, and only then the heavier types.

    Workflow: define pass/fail thresholds first (p95/p99 and error rate, never averages) → model the workload → confirm the target and environment with you → run smoke, then the chosen type, with observability on → interpret → record the baseline.

    Inside:

    • references/test-types.md: the load profile and use case for each of the six types.
    • references/workload-modeling.md: the open model (arrival rate) versus the closed model (VUs), the coordinated-omission trap, traffic mix from real data, parameterized test data, and generator discipline.
    • references/interpreting-results.md: thresholds versus measured values, reading the latency distribution, finding the knee and the first resource to saturate, graceful versus catastrophic failure, recovery, and a report template.

    Safety by design: the skill activates only on an explicit request. It never runs or suggests a load test on its own, never targets production unless you direct it and own that decision, and discards any run where the load generator itself saturated.

    Free and MIT-licensed, part of claude-skills-czl.

    Source on GitHub: this skill · full repository

    How to use

    Skills on Agensi run inside your AI agent. Copy the prompt, paste it into your agent, and it connects to Agensi and installs this skill for you. If a payment is needed, your agent shows it to you first.

    Reviews

    No reviews yet

    Be one of the first to try it. Every listed skill passes our trust checks below.

    Security scanned

    Passed our 8-point scan before listing

    Fresh listing

    Recently published to Agensi

    Free forever

    No account required to browse

    Trust & safety

    Security scanned

    Verified clean 11 days ago

    • Free to download with an account

    Listed11 days ago
    Updated4 days ago

    What's inside

    Frequently Asked Questions