57 lines
1.7 KiB
JavaScript
57 lines
1.7 KiB
JavaScript
// k6 load-test: tenant-scoped read path (`GET /v1/entities/:slug/rows`).
|
|
//
|
|
// Profile: 100 VUs for 60s. The read path is the hottest API surface in
|
|
// production, so the p(99) latency budget is tight and a minimum throughput
|
|
// floor is asserted to catch regressions that pass percentile checks while
|
|
// quietly halving RPS (e.g. accidental serialisation under contention).
|
|
//
|
|
// Run:
|
|
// K6_TARGET_URL=http://localhost:3000 \
|
|
// LOAD_TENANT_API_KEY=tnk_live_xxx \
|
|
// k6 run tests/load/api-read.js
|
|
//
|
|
// Required env:
|
|
// LOAD_TENANT_API_KEY tenant-scoped API key for the test tenant
|
|
// Optional env:
|
|
// LOAD_ENTITY_SLUG entity slug to read (default: load-test-entity)
|
|
|
|
import http from "k6/http";
|
|
import { check, group } from "k6";
|
|
|
|
export const options = {
|
|
scenarios: {
|
|
api_read: {
|
|
executor: "constant-vus",
|
|
vus: 100,
|
|
duration: "60s",
|
|
tags: { suite: "api-read" },
|
|
},
|
|
},
|
|
thresholds: {
|
|
http_req_failed: ["rate<0.01"],
|
|
http_req_duration: ["p(99)<300"],
|
|
http_reqs: ["rate>200"],
|
|
},
|
|
discardResponseBodies: true,
|
|
};
|
|
|
|
const TARGET_URL = __ENV.K6_TARGET_URL || "http://localhost:3000";
|
|
const TENANT_API_KEY = __ENV.LOAD_TENANT_API_KEY || "tnk_load_test_key";
|
|
const ENTITY_SLUG = __ENV.LOAD_ENTITY_SLUG || "load-test-entity";
|
|
|
|
export default function apiReadScenario() {
|
|
group("api-read", function () {
|
|
const params = {
|
|
headers: {
|
|
accept: "application/json",
|
|
authorization: `Bearer ${TENANT_API_KEY}`,
|
|
},
|
|
tags: { name: "api-read" },
|
|
};
|
|
const res = http.get(`${TARGET_URL}/v1/entities/${ENTITY_SLUG}/rows`, params);
|
|
check(res, {
|
|
"status is 200 or 401 or 404": (r) => r.status === 200 || r.status === 401 || r.status === 404,
|
|
});
|
|
});
|
|
}
|