boot-labs.js drives the real admin Prepare-Labs endpoint (reusing the existing session-helper.js from Phase 3A) and records boot time/failure rate; sample-resources.sh samples real docker stats for running Labs. capacity-model.js turns measured per-Lab CPU/memory into a recommended/ warning/hard-admission-control concurrency threshold - no concurrency number is hardcoded as a marketing figure, every input is explicitly placeholder data until measured against the real host. Plus deploy/rollback/smoke-test scripts used by the CI/CD and deployment runbooks. All syntax-checked; validate-compose.sh and capacity-model.js actually run against real inputs.
Load test tooling
Two scripts, run together against whatever stack you point them at:
boot-labs.js— provisions N Labs concurrently via the real admin Prepare Labs endpoint, measures boot success rate and wall-clock timing.GATEWAY_URL=... OWNER_EMAIL=... OWNER_PASSWORD=... node boot-labs.js --count=10sample-resources.sh— run on the Lab Host whileboot-labs.jsruns, samples realdocker statsfor everyrootnode-lab-*container every 5s, writes CSV.
# terminal 1, on the Lab Host:
./infra/scripts/loadtest/sample-resources.sh 180 ./results/run1.csv
# terminal 2, wherever the Gateway is reachable from:
GATEWAY_URL=https://academy.example.com OWNER_EMAIL=... OWNER_PASSWORD=... \
node infra/scripts/loadtest/boot-labs.js --count=10
report-template.md is a filled-in-by-hand summary format — copy it, paste the two scripts'
output in, note the host class it ran against. A run against a dev laptop is not evidence
about the real Hetzner host — every report must say what it ran on.
Feeds docs/CAPACITY_PLANNING.md's worksheet directly: sample-resources.sh's peak
mem_usage/cpu_pct per Lab are exactly the "measured Lab CPU"/"measured Lab RAM" inputs that
worksheet asks for.
Test dimensions this DOESN'T cover yet (documented gaps, not silently skipped): terminal
WebSocket throughput under concurrent load, Gateway HTTP throughput independent of Lab boot,
and steady-state (long-running, not just boot-burst) resource drift. Extend boot-labs.js's
pattern (it already reuses platform/test/session-helper.js) rather than building a separate
tool if/when those are needed.