Load Testing
k6 scripts for smoke, sustained load, and stress testing — targeting the governance pipeline, dashboard, and escalation endpoints. Integrated into the deployment pipeline as a gate between staging and production.
Three Test Profiles
Smoke
1 virtual user, 1 iteration. Validates every endpoint responds correctly — health, pipeline (all verdict paths), shadow mode, dashboard, and escalation. Any failure aborts. Runs first in CI.
Load
Three concurrent scenarios: pipeline submissions ramping to 8 req/s, dashboard polling with 10 virtual users, and escalation queries at 2 virtual users. Measures p95 latency under sustained realistic traffic for 7.5 minutes.
Stress
Ramps pipeline traffic to 50 req/s (100 VUs) and dashboard to 80 VUs. Finds the breaking point, measures when 429s appear, and verifies the system recovers after load drops. Expects degradation but not collapse.
Running Locally
Install k6, then start the API in open mode:
# Start API (no auth, no rate limiting)
GAAS_OPEN_MODE=true GAAS_RATE_LIMIT_ENABLED=false \
uvicorn packages.api.main:app
# Run smoke test
k6 run tests/load/smoke.js
# Run load test with JSON export
k6 run tests/load/load.js --out json=results.json
# Run stress test
k6 run tests/load/stress.js
Override the target URL for remote environments:
K6_BASE_URL=https://staging.example.com K6_API_KEY=gsk_... \
k6 run tests/load/smoke.js
Payload Mix
The load and stress tests select intents from a weighted random pool that exercises all verdict paths through the governance pipeline:
| Scenario | Pipeline Path | Weight |
|---|---|---|
| Clean low-risk | Full pipeline → APPROVE | 50% |
| PCI regulated data | Policy fast-fail → BLOCK | 15% |
| High financial ($75k) | Triggers deliberation → ESCALATE | 15% |
| Minor data (COPPA) | Policy fast-fail → BLOCK | 10% |
| Audit tampering | Policy fast-fail → BLOCK | 10% |
Pass/Fail Thresholds
| Endpoint Group | Metric | Threshold |
|---|---|---|
| Pipeline (live & shadow) | p95 latency | < 2,000ms |
| Dashboard | p95 latency | < 500ms |
| Escalation | p95 latency | < 500ms |
| Health / Metrics | p95 latency | < 200ms |
| Global | Error rate | < 5% |
| Stress (pipeline) | Success rate | ≥ 70% |
Custom Metrics
Beyond standard k6 HTTP metrics, the load tests track governance-specific measurements:
| Metric | Type | Source |
|---|---|---|
gaas_pipeline_latency_ms |
Trend | Extracted from X-GaaS-Pipeline-Latency-Ms response header — server-side pipeline execution time |
gaas_verdicts_approve |
Rate | Fraction of decisions that result in approve or approve_modified |
gaas_error_rate |
Rate | Application-level errors (non-200 on expected-success requests) |
gaas_rate_limit_429s |
Counter | Rate-limit rejections during stress tests |
CI Integration
A k6 smoke run executes automatically as part of the staging gate. Every merge to main deploys to a real staging environment; the gate must pass before that build becomes eligible for promotion to production. The GitHub Actions workflow:
- Builds both container images and pushes them to Amazon ECR, addressed by digest
- Runs database migrations and deploys those exact digests to the staging cluster
- Runs the smoke suite against the deployed service, then a k6 smoke run (1 virtual user, 1 iteration)
- Tags the digests as promotable only if every check passes
load and stress profiles described on this page are run deliberately, not on every merge. What the gate runs is a single-iteration k6 smoke pass — its value is that it exercises the real system, not that it applies load. It runs against the deployed service with authentication and rate limiting on: k6 targets staging through the load balancer using a real organisation API key, so a run exercises the ALB, the container, Postgres and the full authentication path — not a throwaway container with its protections switched off. Correctness thresholds (request-failure rate and check success) are identical to production and are never relaxed; only latency ceilings differ, because staging runs on half of production's CPU and memory.
Environment Variables
| Variable | Default | Description |
|---|---|---|
K6_BASE_URL |
http://localhost:8000 |
Target API base URL |
K6_API_KEY |
(empty) | API key for authenticated environments |
GAAS_OPEN_MODE |
false |
Set to true on the API server to skip authentication |
GAAS_RATE_LIMIT_ENABLED |
true |
Set to false on the API server to disable rate limiting |
Related Pages
- Observability & Alerting — Prometheus metrics that k6 results correlate with
- Intent Declaration API — the pipeline endpoints under test
- Conversational Dashboard — the dashboard endpoints under test