K6 + Grafana + InfluxDB Stack

9 min read

The text summary tells you what the final numbers were. A Grafana dashboard tells you when they changed and what was happening simultaneously — a deploy, a spike, a database backup. Real-time time-series visualisation is the difference between finding a root cause in minutes and spending hours correlating logs.

The stack

K6 metrics pipeline
  • – Streams metrics via --out influxdb
  • – Or --out experimental-prometheus-rw
  • – Real-time, not post-run
  • – Stores every metric sample with timestamp
  • – Optimised for time-series queries
  • – Retains data for trend comparison across runs
  • – Live dashboards during test execution
  • – Community dashboard: ID 2587
  • – Alert on p(95) crossing threshold in real time
  • – Overlay CPU/memory alongside K6 metrics
  • --out experimental-prometheus-rw –
  • Same Grafana dashboards work –
  • Better fit if team already uses Prometheus –

Docker Compose setup

The fastest way to get the full stack running locally is Docker Compose. Create docker-compose.yml:

version: '3.8'
services:
  influxdb:
    image: influxdb:1.8
    ports:
      - "8086:8086"
    environment:
      - INFLUXDB_DB=k6
      - INFLUXDB_HTTP_AUTH_ENABLED=false
 
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
    volumes:
      - grafana_data:/var/lib/grafana
 
volumes:
  grafana_data:

Start the stack:

docker-compose up -d

Run K6 streaming to InfluxDB:

k6 run --out influxdb=http://localhost:8086/k6 script.js

Open Grafana at http://localhost:3000.

Adding the K6 community dashboard

The Grafana community provides a pre-built K6 dashboard (ID 2587) that shows all built-in K6 metrics with sensible layout:

  1. In Grafana, go to Dashboards → Import
  2. Enter dashboard ID 2587 and click Load
  3. Select the InfluxDB data source (add it first under Configuration → Data Sources if needed)
  4. Click Import

The dashboard shows: VU count over time, request rate, p(50)/p(90)/p(95)/p(99) latency as time series, error rate, and check pass rate — all updating live as K6 runs.

What real-time dashboards reveal

A text summary at the end of the test shows you p(95) = 420ms. A Grafana time-series graph shows you:

t=0m:  p(95) = 180ms   (ramp-up phase)
t=5m:  p(95) = 195ms   (steady state)
t=8m:  p(95) = 720ms   ← sudden spike at 8 minutes
t=9m:  p(95) = 850ms
t=11m: p(95) = 200ms   (recovered)

The spike at 8 minutes is invisible in the aggregate average. In Grafana, you can correlate it with a deploy at 7:58, a database backup that started at 7:55, or a cron job that runs at :00 past the hour. The aggregate text summary cannot tell you this.

Combining K6 metrics with server metrics

Grafana's value comes from combining data sources. Add your server's CPU, memory, and database connection metrics alongside K6:

  • Prometheus + Node Exporter: system CPU and memory
  • MySQL/PostgreSQL exporters: database connection count, query latency
  • Application APM (Datadog, New Relic): function-level traces

When http_req_duration starts climbing at t=8m, looking left on the same Grafana panel: did database connections spike? Did CPU hit 100%? Did heap memory start growing? The correlation is immediate.

Prometheus output

If your team already uses Prometheus, use K6's experimental Prometheus remote write output:

k6 run --out experimental-prometheus-rw script.js

Configure the Prometheus endpoint in K6 environment variables:

K6_PROMETHEUS_RW_SERVER_URL=http://localhost:9090/api/v1/write \
k6 run --out experimental-prometheus-rw script.js

The same Grafana dashboards work — Prometheus is just a different data source. Use this if your infrastructure already has Prometheus for application metrics; it avoids adding InfluxDB to the stack.

Retaining data across test runs

One advantage of streaming to InfluxDB/Prometheus over local files: data persists after the test. You can compare this week's p(95) against last week's on the same dashboard, build week-over-week trend panels, and set Grafana alerts that page the team when performance regresses between runs.

Week 1: checkout_flow p(95) = 420ms  ✓
Week 2: checkout_flow p(95) = 580ms  ✓  (38% regression — caught before prod)
Week 3: checkout_flow p(95) = 320ms  ✓  (optimisation merged)

This trend view is impossible with one-off text summaries. It requires a persistent time-series store.

⚠️ Common mistakes

  • Not adding the Grafana data source before importing the dashboard. The dashboard import requires an existing InfluxDB data source named with the database k6. Configure the data source first: URL http://influxdb:8086, database k6, no auth.
  • Running InfluxDB 2.x with the --out influxdb flag. The --out influxdb flag targets InfluxDB 1.x. InfluxDB 2.x uses a different API — use the --out xk6-influxdb extension or stay on InfluxDB 1.8 for simplicity.
  • Not keeping the Docker containers running between test runs. If you stop the InfluxDB container, you lose all historical data. Use a named Docker volume for InfluxDB data to persist it across container restarts.
  • Only looking at the Grafana dashboard during ramp-up. The most important phase to watch is the steady-state hold, when metrics should be stable. Set a browser reminder or Grafana alert so you are watching at the peak VU phase, not just during ramp-up.

🎯 Practice task

Set up the full K6 + Grafana + InfluxDB stack and run a monitored test. 45 minutes.

  1. Create the docker-compose.yml from this lesson and run docker-compose up -d. Verify InfluxDB is accessible at http://localhost:8086 and Grafana at http://localhost:3000.
  2. In Grafana, add an InfluxDB data source: URL http://influxdb:8086, database k6, no authentication.
  3. Import dashboard ID 2587 using the InfluxDB data source.
  4. Write a script targeting https://test.k6.io with a 2-minute ramp to 20 VUs, 5-minute hold, 2-minute ramp down. Add tags to each request.
  5. Run with k6 run --out influxdb=http://localhost:8086/k6 script.js. Switch to Grafana and watch the VU count and p(95) panels update in real time.
  6. After the test ends, note the time of peak VU count on the Grafana dashboard. Click into the http_req_duration panel and look for any latency change during that peak.
  7. Run the same script again. On the Grafana dashboard, use the time range selector to compare the two runs side by side.

// tip to track lessons you complete and pick up where you left off across devices.