Performance testing, part 2: publishing k6 metrics with InfluxDB and Grafana
In part one I wrote about choosing k6 so that performance testing could be self-service: tests as code, lightweight load, and something any engineer could run. That got us running. About two months in, once teams were actually writing and running tests, the next problem showed up, and it was not about generating load at all. It was about what happened to the results.
The gap: results that vanished
By default, a k6 run prints a summary to the console when it finishes and then it is gone. That is fine for a single check on your own machine. It falls apart the moment you want performance testing to be a real, ongoing practice.
- You cannot see trends over time. Is p95 latency creeping up release over release? A console summary cannot tell you.
- You cannot easily compare runs. Did today’s change make things better or worse than last week?
- You cannot share results. Leadership and other engineers wanted to see how things looked, and screenshots of a terminal are not a dashboard.
Self-service testing only sticks if people can see the results. So the second phase of the work was less about load generation and more about publishing metrics and putting dashboards in front of people. That is where InfluxDB and Grafana came in.
Why InfluxDB
k6 can stream its metrics out in real time while a test runs, and InfluxDB was a natural place to send them. It is a time-series database, and performance metrics are time-series data at heart: response times, throughput, error counts, and the number of virtual users, all stamped against the moment they happened.
Pointing k6 at InfluxDB meant every run was captured and kept, not thrown away. Instead of a single summary, we had a growing history of every test, queryable and ready to chart.
Why Grafana
Grafana sits on top of InfluxDB and turns those stored metrics into dashboards. Connecting the two gave us live, visual views of a test:
- Latency percentiles such as p95 and p99, which matter far more than averages for a real user experience.
- Throughput in requests per second.
- Error rate over the run.
- Virtual users over time, so you can line up load against response.
The payoff was twofold. During a run, anyone could watch the dashboard live instead of squinting at a terminal. After a run, the history let us compare against previous tests and catch regressions. That visibility reinforced exactly the goal from part one: performance testing as a shared, self-service practice rather than a black box owned by one person. There is even a ready-made k6 dashboard for Grafana, so we did not start from a blank page.
The complexity it added
This was a real step up in capability, but I want to be honest that it was also a step up in moving parts. A console summary has no infrastructure. Once you add InfluxDB and Grafana, you are running and operating two more systems, and a few things need care:
- Metric cardinality. k6 can emit high-cardinality tags, and InfluxDB does not love high cardinality. Left unchecked it bloats storage and slows queries, so it is worth trimming the tags you actually need.
- Retention and downsampling. If you want long history, you need a retention policy and probably downsampling, or the data grows without bound.
- Output overhead at high load. Streaming every metric in real time adds overhead, and at very high request rates that stream itself can become a bottleneck. It is worth testing that the observability path keeps up with the load you are generating.
None of these are dealbreakers. They are just the price of turning a quick test into an observable one, and they are worth planning for up front.
The takeaway
k6 got performance testing into everyone’s hands. InfluxDB and Grafana are what made it stick, because they turned isolated runs into a history we could trend, compare, and share. If you adopt k6 for anything ongoing, decide early where the metrics will live and who will look at them. The dashboard is what makes performance testing a habit instead of a one-off.