k6
Developer-friendly performance testing in JavaScript. CLI-first, CI-native, and now part of Grafana Labs.
Overview
k6, created by Load Impact in 2016 and acquired by Grafana Labs in 2021, is a modern load testing tool designed for developers. Tests are written in JavaScript (actually a V8-based Go runtime) and executed from the command line. k6 is built for CI/CD: it returns exit codes, outputs machine-readable metrics, and integrates natively with Grafana for visualisation.
In 2026, k6 is the default choice for teams that want code-based performance testing with modern developer experience. It is particularly strong for API load testing and can simulate thousands of concurrent virtual users from a single machine.
What it's used for
k6 is ideal when:
- Developer-centric performance testing: Tests are JavaScript code, version-controlled, and reviewed in PRs.
- API load testing: Simulate thousands of concurrent users hitting REST, GraphQL, or gRPC endpoints.
- CI/CD integration: Run performance tests on every commit with pass/fail thresholds.
- Real-time monitoring: Stream results to Grafana dashboards during test execution.
Pros & Cons
Pros
- JavaScript syntax — familiar to most developers
- Extremely fast execution (Go-based engine)
- Native CI/CD integration with thresholds and exit codes
- Excellent Grafana integration for visualisation
- Free and open source with generous cloud options
Cons
- Browser-level testing requires k6 Browser (separate, less mature)
- No GUI for test creation — everything is code
- JavaScript-only — not suitable for Java or Python teams
- Distributed load testing requires k6 Cloud or custom orchestration
- Less mature for complex web app scenarios than JMeter or NeoLoad
Platforms & Integrations
k6 runs on Windows, macOS, and Linux. It requires no runtime dependencies beyond the k6 binary. Cloud execution is available via k6 Cloud (Grafana).
Pricing
| Tier | Cost | Includes |
|---|---|---|
| Open Source | Free | Unlimited local execution, all core features |
| k6 Cloud | From $59/mo | Cloud execution, distributed load, analytics, 50 VU minimum |
| Enterprise | Custom | Private cloud, dedicated support, custom SLAs |
NZ Context
k6 is rapidly becoming the standard for API performance testing in NZ tech companies. Startups like Figured and Crimson Education use k6 for load testing their APIs. NZ developer job postings increasingly list k6 as a preferred performance testing tool. For NZ teams already using Grafana for monitoring, k6 is a natural extension.
Alternatives
- JMeter — More mature for complex web scenarios. GUI-based test creation.
- Gatling — Scala-based with excellent reporting. Better for high-concurrency scenarios.
- Artillery — JavaScript/JSON-based load testing. Similar developer experience to k6.
When to choose k6
A quick decision guide for NZ teams evaluating performance testing options.
| Choose k6 when… | Choose something else when… | Combine with… |
|---|---|---|
| Your team already writes JavaScript and tests live in the same repo as the code | Non-technical stakeholders need to create or modify tests — JMeter's GUI is a better fit | Grafana — stream k6 metrics directly into existing dashboards for real-time analysis during load runs |
| You need pass/fail thresholds in CI — e.g. p95 latency must stay under 300 ms or the pipeline fails | You need realistic browser-level load (full page renders, JS execution) — Gatling or Playwright-based tooling handles this better | InfluxDB — persist historical run data so you can track performance trends across releases |
| The target is a REST, GraphQL, gRPC, or WebSocket API — not a server-rendered web application | Your team is Java or Python — Gatling (Scala/Java) or Locust (Python) will fit the team's existing skills better | Playwright — use k6 for API/backend load and Playwright for UI-layer performance spot-checks; they cover different failure modes |
| You want a single binary with no JVM or runtime dependencies — fast to install in Docker or ephemeral CI containers | You need to generate more than a few thousand VUs from one machine — distributed load requires k6 Cloud or custom Kubernetes orchestration | Postman — use Postman for exploratory API testing and contract validation; k6 for sustained load; they share the same HTTP layer knowledge |
What I would do
Practitioner judgment on tool adoption, team onboarding, and when to swap.
The bottom line: k6 is the right default for API load testing in teams that write JavaScript — but only if you set meaningful thresholds. A k6 run with no thresholds is just a report; a k6 run with p95 and error-rate gates is a quality signal your CI pipeline can enforce.
Interview questions
Questions you are likely to get if you list k6 on your CV — with what interviewers are really testing for.
What is a k6 threshold, and why does it matter more than just reading the output report?
What they’re really testing: Whether you understand that k6 is a quality gate, not just a metrics collector — and that a test with no thresholds provides information but no enforcement.
Strong answer covers: Thresholds define pass/fail criteria (e.g. p95 < 300ms, error_rate < 0.01) and cause k6 to return a non-zero exit code when breached; that exit code is what lets a CI pipeline like GitHub Actions or Azure DevOps block a deployment; NZ context — a team at a government agency like Revenue NZ could set a threshold tied to their SLA commitments before each tax-season release.
When would you choose k6 over JMeter for a performance testing project?
What they’re really testing: Whether you can make a reasoned tool decision rather than defaulting to whichever tool you learned first — and whether you understand the trade-offs in team capability, test complexity, and CI integration.
Strong answer covers: k6 wins when the team writes JavaScript, tests need to live in the same repo as the code and be PR-reviewed, and CI integration with exit codes matters; JMeter wins when non-technical stakeholders need to author tests via GUI or when complex browser-level scenarios are required; a NZ-specific signal — e.g. a Wellington SaaS startup where devs already use Node would get more value from k6 than retooling for JMeter’s XML test plans.
You’re a QA engineer at an Auckland fintech and the business wants a load test before launching open banking APIs to NZ consumers. How would you design the k6 test suite?
What they’re really testing: Whether you can translate a business risk into a test strategy — choosing the right load profile, identifying which endpoints matter, and thinking about data privacy constraints in a regulated environment.
Strong answer covers: Mapping the highest-risk journeys (consent flow, account data retrieval, payment initiation); choosing a ramp-up load profile that reflects real adoption curves rather than an arbitrary spike; using anonymised or synthetic test accounts to avoid touching real customer data under the Privacy Act 2020; setting thresholds aligned to the open banking API response-time SLA; and running against a staging environment that mirrors production infrastructure.
Your k6 tests pass locally but the p95 latency threshold fails consistently in CI. How do you investigate?
What they’re really testing: Whether you can systematically diagnose environmental differences rather than dismissing CI results as noise or blindly tuning thresholds upward.
Strong answer covers: Checking whether the CI runner is CPU/network constrained compared to your local machine (k6 is Go-based and CPU-sensitive at high VU counts); verifying the target environment is the same (staging vs localhost); inspecting k6’s --out metrics to see if the latency spike is uniform or only affects specific endpoints; considering whether the CI environment shares resources with other jobs; and using k6 run --vus 1 as a baseline to separate network latency from load-induced degradation.
How would you structure a k6 test suite for a large NZ e-commerce platform so it stays maintainable as the API grows?
What they’re really testing: Whether you think about test architecture and long-term maintainability, not just writing a single script that works once.
Strong answer covers: Separating shared helpers (auth, data setup) into reusable modules imported across test files; grouping scripts by journey or service boundary rather than one monolithic file; using k6 scenarios to define different load profiles (smoke, load, soak, spike) without duplicating business logic; storing threshold definitions in a shared config so they can be tightened centrally; and treating the k6 suite as production code — reviewed in PRs, linted, and kept in the same repo as the service it tests, which is standard practice at NZ-scale platforms like Trademe or Pushpay.