|claim|login
RepoCritics — Review. Share. Archive. Every open-source repo.

grafana/k6

Wiki: grafana/k6

Source: https://github.com/grafana/k6

Last synced 2026-07-16 · 1239 words · Edit wiki on GitHub →

grafana/k6

> A load-testing tool where tests are JavaScript files run by a Go engine — scripting ergonomics of JS, throughput of a single Go process.

GitHub repo · Official website · License: AGPL-3.0

Overview

k6 is a load- and performance-testing tool. You write a test as an ES2015+ JavaScript file that exports a default function; k6 runs that function repeatedly across many concurrent "virtual users" (VUs) and records timing metrics. The scripting layer is JavaScript, but the runtime is Go — the JS is executed by an embedded interpreter, not Node.js, so the tool ships as a single static binary with no runtime dependency1.

It began as the open-source engine of Load Impact and was developed publicly from 2016; Grafana Labs acquired Load Impact in 2021 and folded the project into its observability stack, which is why the canonical repo now lives under grafana/2. The framing is "like unit testing, for performance": tests are code, live in version control, and run in CI, rather than being clicked together in a GUI. As of 2026 it is among the most-used code-first load-testing tools, with ~31k stars and active weekly commits.

The defining tension is the JavaScript-that-isn't-Node model. You get a familiar scripting language and a genuinely good developer experience, but you do not get npm, the Node standard library, or a Node event model for free. This is the single most common source of surprise for new users, and it shapes almost every production decision below.

Getting Started

# macOS
brew install k6
# Debian/Ubuntu
sudo apt-get install k6      # after adding the Grafana apt repo
# or grab a static binary from GitHub Releases
// script.js
import http from "k6/http";
import { check, sleep } from "k6";

export const options = {
  thresholds: {
    http_req_duration: ["p(99) < 3000"], // fail the run if p99 > 3s
  },
  stages: [
    { duration: "30s", target: 15 },     // ramp up to 15 VUs
    { duration: "1m",  target: 15 },     // hold
    { duration: "20s", target: 0 },      // ramp down
  ],
};

export default function () {
  const res = http.get("https://test.k6.io");
  check(res, { "status is 200": (r) => r.status === 200 });
  sleep(1);
}
k6 run script.js

Architecture / How It Works

Each virtual user is an isolated JavaScript runtime. k6 embeds goja, a pure-Go ES5.1+/ES2015+ interpreter, and gives every VU its own goja instance3. VUs do not share JavaScript state; the only ways to share data are explicit — the SharedArray object (read-only, memory-deduplicated across VUs), the built-in k6/execution module, or external systems. This isolation is what lets one process drive thousands of VUs, but it also means the mental model is "N independent script copies", not "one shared program".

Because goja is not V8 and the environment is not Node, network and system I/O are implemented as Go-backed built-in modules (k6/http, k6/ws, k6/net/grpc, k6/browser, and others) rather than as JS libraries. Async support (promises, async/await) runs on an event loop k6 added specifically for these modules; older synchronous code and the newer async APIs coexist. To use third-party JS you must bundle it to a single file with a tool like webpack or esbuild first, or pull it from k6's curated jslib — you cannot npm install into a running test.

The workload model is built from executors. Rather than only "N users for M minutes", you compose scenarios from executors such as constant-vus, ramping-vus, constant-arrival-rate, and ramping-arrival-rate. The arrival-rate executors are the important ones: they hold a target requests per second independent of response latency (an open model), which is what you want for realistic capacity testing; VU-based executors instead hold a fixed number of concurrent users (a closed model) and will slow down under load.

Metrics are typed — Counter, Gauge, Rate, Trend — and built-ins like http_req_duration are Trends you can attach thresholds to for pass/fail. Native functionality is extended through xk6: extensions are Go code compiled into a custom k6 binary, which is how features like the browser and SQL/Kafka outputs originate before some are absorbed into core.

Production Notes

One process, one machine — by default. Open-source k6 does not distribute a run across nodes on its own. A single k6 instance is limited by the CPU and RAM of the box it runs on. To scale out you use grafana/k6-operator on Kubernetes (which shards the script across pods) or Grafana Cloud k6. Teams routinely discover this only after hitting a per-machine ceiling.

VU memory is real. Each VU holds a live JS runtime; footprint depends on the script but budget on the order of single-digit MB per VU, more with large imported data or the browser module. Set discardResponseBodies: true when you don't assert on bodies — retained response bodies are a frequent cause of runaway memory at high VU counts.

goja is not V8. Most modern syntax works, but performance characteristics differ and some libraries relying on V8-specific behavior, native addons, or the full Node API will not run. Heavy per-iteration JS (JSON parsing, crypto, regex) is executed by the interpreter and can make the load generator itself the bottleneck rather than the target — watch k6's own CPU.

Results are not stored unless you route them. By default k6 prints an end-of-test summary and discards the time series. For dashboards or historical comparison you must stream output (--out) to Prometheus remote-write, InfluxDB, JSON, CSV, or a cloud backend. Plan the results pipeline before, not after, the first big run.

Browser testing is heavy. The k6/browser module drives real Chromium via the DevTools Protocol; it is excellent for a handful of browser VUs but does not scale like protocol-level HTTP VUs — mixing the two in one test needs care.

Licensing. k6 is AGPL-3.0. For running tests this is a non-issue, but embedding k6 into a distributed/hosted product, or vendoring its code, carries the AGPL's network-copyleft obligations — worth a legal check before you build on top of it.

When to Use / When Not

Use when:

  • You want load tests as versioned, reviewable code inside CI rather than a GUI.
  • Your team already reads JavaScript and you want low-friction scripting.
  • You need an arrival-rate (open) model for realistic RPS-driven capacity tests.
  • You want a single dependency-free binary and clean Prometheus/Grafana output.

Avoid when:

  • You need built-in, zero-ops distributed generation without running Kubernetes

or paying for a cloud tier — Locust distributes out of the box.

  • Your test logic depends on real npm packages or the Node standard library.
  • You're testing browser-heavy flows at very large scale (browser VUs don't

scale like HTTP VUs).

  • AGPL is a blocker for embedding the engine into a proprietary hosted product.

Alternatives

  • locustio/locust — Python-scripted load tests with built-in distributed workers;

use it when you want native scale-out and prefer Python to JavaScript.

  • gatling/gatling — JVM tool with a Scala/Java DSL and strong HTML reports; use

it in JVM shops that want detailed reporting out of the box.

  • apache/jmeter — mature, GUI-driven, huge protocol/plugin coverage; use it when

non-coders must build test plans or you need a protocol k6 lacks.

  • artilleryio/artillery — Node.js-based, YAML/JS configs; use it when you want a

genuine Node runtime and npm ecosystem in your tests.

  • tsenart/vegeta — Go HTTP load tester as CLI/library; use it for simple

constant-rate HTTP benchmarking without a scripting layer.

History

VersionDateNotes
public dev2016Repo opened; developed as Load Impact's OSS engine2.
1.0 announce2017k6 announced publicly as a code-first load tool.
acquisition2021Grafana Labs acquires Load Impact; project moves to grafana/k62.
browser merge2023xk6-browser folded toward core as the k6/browser module.
1.0.02025First stable major release; API stability commitments4.

References

  1. ^ grafana/k6 README — "A modern load testing tool, using Go and JavaScript."

https://github.com/grafana/k6

  1. ^ Grafana Labs, "Load Impact joins Grafana Labs" / k6 project background.

https://grafana.com/oss/k6/

  1. ^ goja — ECMAScript interpreter in pure Go, the JS engine embedded in k6.

https://github.com/dop251/goja

  1. ^ k6 releases. https://github.com/grafana/k6/releases

Tags

load-testing, performance-testing, go, javascript, cli, devops, ci-cd, benchmarking, grafana, agpl, http