Grafana k6
Load tests as code. k6 scripts are JavaScript, live in your repository, run in your pipeline, and treat performance budgets as executable assertions.
Where it shines
The developer experience is the point: tests are plain code, reviewable in pull requests, versioned with the application they test. Thresholds make pass/fail criteria executable — a CI step fails when p95 exceeds budget. The Go-based runtime drives substantially more virtual users per generator node than JVM-based tools. Native support for HTTP/2, WebSockets and gRPC covers modern API stacks well.
import http from "k6/http";
import { check } from "k6";
export const options = {
scenarios: {
peak: {
executor: "ramping-arrival-rate", // open model
startRate: 50, timeUnit: "1s",
stages: [
{ target: 420, duration: "20m" }, // ramp
{ target: 420, duration: "60m" }, // plateau
],
preAllocatedVUs: 6000,
},
},
thresholds: {
http_req_duration: ["p(95)<500", "p(99)<1200"],
http_req_failed: ["rate<0.001"],
},
};
export default function () {
const res = http.get("https://api.example.com/catalogue");
check(res, { "has results": (r) => r.json("items.length") > 0 });
}
Limitations to plan around
No browser-level protocol recording (scripts are written, not captured); the JavaScript API is not Node.js (no npm runtime modules, though bundling helps); and legacy enterprise protocols (JMS, JDBC, Citrix) are out of scope — that's JMeter territory.
Our k6 practice
Arrival-rate executors for open-model realism; scenario configs per test type sharing one script codebase; results streamed to Grafana for live dashboards; and threshold-gated CI jobs that run smoke-level performance tests on every merge.