k6 Load Testing (Local + CI)
Goal: provide a repeatable, gated, and archivable performance baseline and regression workflow.
1. Start Backend (local profile)
This repository ships with a local load-test seed (enabled by default in the local profile):
- Tenant:
tenantId=1 - User:
loadtest/loadtest123
Set the JWT key (to avoid startup errors):
export JWT_KEY="ci-integration-jwt-key-32chars-xK9mN2pL5qR8vW3y"Start the backend (example):
mvn -f platform-backend/pom.xml -pl backend-web -am spring-boot:run \
-Dspring-boot.run.profiles=localDefault Base URL:
http://localhost:8000/record-platform/api/v12. Install k6 (macOS)
brew install k6If local k6 is unavailable, use --engine auto to fall back to Docker (grafana/k6:0.49.0).
3. Quick Run
3.1 Smoke regression (recommended)
When K6_SCENARIO=all (default), runs file-query + core-mixed.
bash tools/k6/run-local.sh --profile smoke --scenario all --engine autoThe core-mixed scenario combines file query and chunk upload flows in a weighted mix. By default, 70% of iterations run query flows and 30% run upload flows. Control the query/upload ratio with the MIX_QUERY_WEIGHT environment variable (0-100, default 70):
MIX_QUERY_WEIGHT=50 bash tools/k6/run-local.sh --profile smoke --scenario core-mixed --engine auto3.2 Load test
When K6_SCENARIO=all (default), runs file-query + chunk-upload.
bash tools/k6/run-local.sh --profile load --scenario all --engine auto3.3 Single scenario
bash tools/k6/run-local.sh --profile smoke --scenario file-query --engine auto
bash tools/k6/run-local.sh --profile smoke --scenario core-mixed --engine auto
bash tools/k6/run-local.sh --profile smoke --scenario chunk-upload --engine auto
bash tools/k6/run-local.sh --profile load --scenario chunk-upload --engine auto4. API Contract (per backend code)
4.1 Login
POST /api/v1/auth/loginContent-Type: application/json- Body:
{"username":"...","password":"..."} - Must include
X-Tenant-IDheader
4.2 Query chain
GET /api/v1/files?pageNum=1&pageSize=10(basic)GET /api/v1/files?pageNum=1&pageSize=10&keyword=...&keywordMode=PREFIX(keyword)GET /api/v1/files?pageNum=1&pageSize=10&keyword=...&keywordMode=PREFIX&status=1&startTime=...&endTime=...(combo)GET /api/v1/files/stats
4.3 Upload chain
POST /api/v1/upload-sessions(@RequestParam)fileName/fileSize/contentType/chunkSize/totalChunks(optionalclientId)
PUT /api/v1/upload-sessions/{clientId}/chunks/{chunkNumber}(multipart/form-data)file/clientId/chunkNumber
POST /api/v1/upload-sessions/{clientId}/complete(clientId)GET /api/v1/upload-sessions/{clientId}/progress
4.4 Cleanup chain
DELETE /api/v1/files?identifiers=...- Teardown searches by
runIdand batch soft-deletes.
5. Gate Thresholds
Global:
http_req_failed < 1%checks > 99%
Query chain:
files_basic p95 < 800msfiles_keyword p95 < 800msfiles_combo p95 < 1000msfiles_stats p95 < 800ms
Upload chain:
upload_start p95 < 1200msupload_chunk p95 < 1500msupload_complete p95 < 1500msupload_e2e_ms p95 < 6000ms
6. Report Artifacts
Each run outputs to RESULT_DIR:
summary.txt(includes per-endpoint p50/p90/p95, error rate, request count, threshold results, failed samples)summary.jsonmetrics.jsonquery-baseline.json(structured endpoint metrics + threshold results for report backfill)run-meta.json(runId/profile/scenario/engine/timestamp/baseUrlMask)
Default directory: tools/k6/results/<RUN_ID>/
7. CI Smoke
Workflow: .github/workflows/perf-smoke.yml
run-ci.sh required environment variables (unified naming only):
BASE_URLTENANT_IDUSERNAMEPASSWORD
GitHub Actions Secrets (same names as unified variables):
BASE_URLTENANT_IDUSERNAMEPASSWORD
Supports:
- Manual trigger (
workflow_dispatch)
Optional:
- When manually triggered, you can choose whether to include the
chunk-uploadscenario (include_chunk_upload=true).
8. Common Failure Troubleshooting
401: Wrong username/password or invalid token.400 missing tenant identifier: Request missingX-Tenant-IDheader.429: Global rate limit triggered; lowerVUSor arrivalrate.- Upload failure: Verify that
chunkusesmultipart/form-datawith all required fields.