Test Tools · Performance Testing

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).

Windows macOS Linux JavaScript REST GraphQL gRPC WebSocket Docker Grafana InfluxDB GitHub Actions GitLab CI Jenkins Azure DevOps

Pricing

TierCostIncludes
Open SourceFreeUnlimited local execution, all core features
k6 CloudFrom $59/moCloud execution, distributed load, analytics, 50 VU minimum
EnterpriseCustomPrivate 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.

If…
I was a QA engineer at CloudBooks and we had just moved our payroll API to a microservices architecture with a big AU/NZ payroll run every Sunday night
I would…
Write a k6 soak test that runs at realistic Sunday-night concurrency (e.g. 2,000 VUs) for 30 minutes against the staging environment, with a strict threshold of p99 < 2 s and error rate < 0.1%. Wire it into the Saturday night CI pipeline so failures block the Sunday deploy. This gives us a predictable signal before real payroll data is at stake — the kind of latency spike that only surfaces under sustained load, not in 5-minute smoke tests.
If…
I was leading QA at ListRight and we were shipping a major search ranking algorithm change ahead of a long-weekend traffic spike
I would…
Run a k6 spike test that ramps from baseline (500 VUs) to peak traffic (3,000 VUs) in 60 seconds — the shape of a long-weekend browse surge — targeting the search and listing-view endpoints specifically. I would not reach for JMeter here: ListRight's engineers already work in JavaScript and k6 scripts can be PR-reviewed by the same developers who changed the ranking logic. I would stream results to Grafana Cloud so the infrastructure team can correlate k6 VU counts with real AWS CloudWatch metrics side-by-side.
If…
I was a tester at TransitNZ on a team that had inherited a legacy JMeter suite and was debating a migration to k6
I would…
Not do a big-bang migration. I would port one critical journey — say, the RUC licence purchase flow — to k6 and run both tools against the same environment for two sprints to compare results. If k6 catches the same issues in less time and the team finds the scripts easier to maintain, that's a concrete case for the migration. If the JMeter suite has complex think-time logic or certificate-based auth scenarios that k6 handles awkwardly, I would keep those tests in JMeter and use k6 only for the new API-layer tests going forward. Tool choice should follow the team's capability, not hype.

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.

Learn more