Files
HiveGrid-Wireframes/hivegrid-cloud/tests/load/README.md
T

4.0 KiB

Load test suite (k6)

This directory contains the production-rehearsal k6 load tests for the boilerplate. They are the load-tier companion to the unit, integration, and verifier layers — useful before a release cut, after a perf regression suspicion, or when sizing a new staging tier.

The suite is opt-in. CI does not run it by default because it requires a deployed target environment, a tenant API key, and a k6 binary on the runner. scripts/run-load-tests.mjs is the safe wrapper: it SKIPs cleanly when either prerequisite is missing.

Install k6

k6 is a single Go binary — install it from the upstream packages:

Verify the install with k6 version. The runner script checks the same.

Scripts

Script Profile Thresholds
login.js 50 VUs, 30s ramp + 30s hold against POST /v1/auth/login http_req_failed: rate<0.05, http_req_duration: p(99)<800ms, http_req_duration{name:login}: p(95)<400ms
api-read.js 100 VUs, 60s constant against GET /v1/entities/<slug>/rows http_req_duration: p(99)<300ms, http_reqs: rate>200/s
api-mutating.js 30 VUs, 30s constant against POST /v1/entities/<slug>/rows http_req_duration: p(99)<600ms
scenarios.js Composite — runs all three back-to-back Per-suite thresholds tagged by name:

Each per-script file is also runnable standalone — useful when isolating a regression to one path.

Threshold rationale

  • http_req_failed: rate<0.05 on login allows for 401s from the synthetic account while still catching server-side 5xx storms.
  • http_req_duration: p(99)<800ms on login covers password hashing + session creation under realistic contention. Tighten as the auth path matures.
  • http_req_duration{name:login}: p(95)<400ms keeps the typical login fast; it is the user-facing budget, not the worst-case.
  • http_req_duration: p(99)<300ms on the read path matches the warm-cache-hit budget for the hottest API surface.
  • http_reqs: rate>200/s is a throughput floor — percentile checks alone miss regressions that quietly halve RPS under contention.
  • http_req_duration: p(99)<600ms on the mutating path covers transactional write + audit + queue enqueue.

If a threshold becomes too tight for a particular environment (e.g. a small staging tier), override at invocation time with k6 run --threshold rather than editing the script — keep the production budget in source.

Running locally

# Single script
K6_TARGET_URL=http://localhost:3000 \
LOAD_TENANT_API_KEY=tnk_load_test_key \
k6 run tests/load/login.js

# Full suite via the safe runner (SKIPs if k6 is missing or target down)
K6_TARGET_URL=http://localhost:3000 \
LOAD_TENANT_API_KEY=tnk_load_test_key \
pnpm run verify:load

Required env vars:

  • K6_TARGET_URL — base URL of the target environment (default http://localhost:3000).
  • LOAD_TENANT_API_KEY — tenant-scoped API key for the test tenant. The read/mutating scripts default to a placeholder that will return 401 — fine for SKIP-rehearsal but not for a real load run.

Optional env vars:

  • LOAD_LOGIN_EMAIL / LOAD_LOGIN_PASSWORD — synthetic login credentials.
  • LOAD_ENTITY_SLUG — entity slug to target on the read/mutating paths.

Stress vs. smoke

To scale a smoke run down, pass --vus 5 --duration 10s to k6 run. To scale a stress run up, increase the per-script VUs via the k6 CLI rather than editing the file. The committed VU counts are the production-rehearsal contract.

Safety notes

  • Never point a load test at production without an explicit human approval.
  • Mutating runs append synthetic rows tagged with load-test-row-* so they can be cleaned up by a downstream verifier. Pick a throwaway tenant.
  • Load tests are part of the production-readiness ladder, not part of CI Auto-Mode. Keep verify:load out of the default lane until a target environment is wired up.