I’ve spent years firefighting production outages that could have been prevented with a simple load test. The problem usually isn’t the code—it’s how the code behaves when 5,000 people hit the same endpoint at once. That’s why I shifted my workflow to k6. If you’re looking for a grafana k6 load test tutorial that cuts through the fluff and gets you to actual results, you’re in the right place.

Unlike older tools that require heavy XML configurations, k6 allows us to write tests in JavaScript. This means we can version control our tests and integrate them directly into our CI/CD pipelines. If you’re wondering whether to stick with legacy tools, I highly recommend checking out my k6 vs jmeter comparison to see why the industry is moving toward code-based testing.

Prerequisites

Step 1: Writing Your First k6 Script

The beauty of k6 is its simplicity. You don’t need a GUI to start; a single `.js` file is all it takes. Create a file named loadtest.js. I’ve structured this example to simulate a realistic user flow: hitting a homepage and then fetching a specific resource.

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '30s', target: 20 }, // Ramp-up to 20 users
    { duration: '1m', target: 20 },  // Stay at 20 users
    { duration: '30s', target: 0 },  // Ramp-down to 0
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'], // 95% of requests must be under 500ms
  },
};

export default function () {
  const res = http.get('https://test-api.k6.io/');
  
  // Validate that the response is a 200 OK
  check(res, {
    'status is 200': (r) => r.status === 200,
  });

  sleep(1); // Simulate user think time
}

In this script, I used stages. This is critical because jumping from 0 to 1,000 users instantly often crashes a system due to connection spikes rather than actual load. Ramping up allows you to see exactly at which user count the latency starts to climb.

Step 2: Executing the Load Test

Now that we have our script, we run it from the terminal. I usually start with a small, local run before scaling it up to the cloud.

Run the following command in your terminal:

k6 run loadtest.js

As you run this, k6 will output a live summary in your terminal. Pay close attention to http_req_duration. If the p(95) value exceeds your threshold, k6 will mark the test as failed. This is the foundation of automated quality gates. For those looking to automate this further, I’ve detailed performance testing in github actions to help you catch regressions before they merge.

Step 3: Visualizing Results with Grafana

Terminal output is great for quick checks, but for a professional grafana k6 load test tutorial, we need visual data. The most common way to do this is by streaming k6 metrics to an InfluxDB or Prometheus database and visualizing them in Grafana.

Here is the architectural flow I recommend: k6 $\rightarrow$ InfluxDB $\rightarrow$ Grafana.

To stream your results, run k6 with the output flag:

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

Once the data is flowing, you can import the official k6 Grafana dashboard (ID: 19049). This gives you immediate visibility into request rates, error percentages, and latency distribution. As shown in the image below, the visual spike in response time usually correlates perfectly with the ramp-up of virtual users (VUs).

Grafana dashboard showing a correlation between Virtual User count and API response time spikes
Grafana dashboard showing a correlation between Virtual User count and API response time spikes

Pro Tips for Realistic Testing

Troubleshooting Common Issues

Issue Cause Solution
Socket Hang Up Server cannot handle concurrent connections Lower the target VUs or increase server ulimit
k6 Memory Exhaustion Too many VUs on a small machine Run k6 in a Docker container with increased memory limits
429 Too Many Requests Rate limiting is active on the target Whitelist your test IP or adjust rate limits for the test environment

What’s Next?

Now that you can run a basic load test, the next step is to move toward Soak Testing (running a moderate load for 24 hours to find memory leaks) and Stress Testing (pushing the system until it actually breaks). If you want to dive deeper into infrastructure optimization, I recommend exploring how to tune your Nginx or Node.js settings based on the bottlenecks you’ve just discovered.