Modern QA2026k6 (Grafana k6) — tiles
Log inJoin
9 / 95 · 05 Performance & Chaos Engineering · k6 and Locust: Modern Load Testing Tools← prev⊞ allnext →☰ Read as one page

2.1k6 (Grafana k6)

k6 is a developer-centric load testing tool written in Go with JavaScript scripting. It has become the industry standard for teams practicing shift-left performance testing. Its key strengths are low resource footprint, native CI integration, and a scripting model that developers actually enjoy using.

Why k6 Wins for CI/CD

  • Single binary. No JVM, no dependencies. Download and run.
  • JavaScript scripting. Familiar syntax for most development teams.
  • Threshold-based pass/fail. Define SLOs directly in the test -- if they fail, the exit code is non-zero, and CI fails.
  • Built-in metrics export. Stream to Grafana, Datadog, Prometheus, or JSON.
  • Scenarios engine. Model multiple traffic patterns in a single test file.

Complete k6 Example: E-Commerce Load Test

// k6-load-test.js -- Realistic e-commerce load test with multiple scenarios
import http from 'k6/http';
import { check, sleep, group } from 'k6';
import { Rate, Trend } from 'k6/metrics';

// Custom metrics for business-specific SLOs
const errorRate = new Rate('errors');
const checkoutDuration = new Trend('checkout_duration');

// Traffic shaping: ramp up, sustain, spike, cool down
export const options = {
  scenarios: {
    // Steady-state browsing traffic (70% of users)
    browse: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '2m', target: 100 },   // ramp up
        { duration: '5m', target: 100 },   // steady state
        { duration: '1m', target: 300 },   // spike
        { duration: '5m', target: 100 },   // back to steady
        { duration: '2m', target: 0 },     // ramp down
      ],
      exec: 'browseProducts',
    },
    // API consumers hitting the search endpoint (30% of traffic)
    api_search: {
      executor: 'constant-arrival-rate',
      rate: 50,            // 50 requests per second
      timeUnit: '1s',
      duration: '15m',
      preAllocatedVUs: 20,
      maxVUs: 100,
      exec: 'searchAPI',
    },
  },
  thresholds: {
    http_req_duration: ['p(95)<500', 'p(99)<1500'],  // SLO enforcement
    errors: ['rate<0.01'],                             // <1% error rate
    checkout_duration: ['p(95)<3000'],                 // checkout under 3s
  },
};

export function browseProducts() {
  group('Homepage', () => {
    const res = http.get('https://store.example.com/');
    check(res, {
      'homepage status 200': (r) => r.status === 200,
      'homepage loads under 2s': (r) => r.timings.duration < 2000,
    });
    errorRate.add(res.status >= 400);
  });

  sleep(Math.random() * 3 + 1); // realistic think time: 1-4 seconds

  group('Product Page', () => {
    const productId = Math.floor(Math.random() * 1000) + 1;
    const res = http.get(`https://store.example.com/products/${productId}`);
    check(res, {
      'product page status 200': (r) => r.status === 200,
      'has product title': (r) => r.body.includes('<h1'),
    });
    errorRate.add(res.status >= 400);
  });

  sleep(Math.random() * 5 + 2); // browsing think time: 2-7 seconds
}

export function searchAPI() {
  const queries = ['laptop', 'phone', 'headphones', 'keyboard', 'monitor'];
  const query = queries[Math.floor(Math.random() * queries.length)];

  const res = http.get(`https://api.store.example.com/search?q=${query}`, {
    headers: { 'Authorization': `Bearer ${__ENV.API_TOKEN}` },
  });

  check(res, {
    'search returns 200': (r) => r.status === 200,
    'search returns results': (r) => JSON.parse(r.body).results.length > 0,
    'search under 300ms': (r) => r.timings.duration < 300,
  });
  errorRate.add(res.status >= 400);
}

Running k6

# Local execution with default output
k6 run k6-load-test.js

# With environment variables for secrets
k6 run -e API_TOKEN=secret123 k6-load-test.js

# Output results to Grafana Cloud k6
k6 cloud k6-load-test.js

# Output to JSON for CI analysis
k6 run --out json=results.json k6-load-test.js

# Run with a specific scenario only
k6 run --scenario browse k6-load-test.js

k6 Executor Types

Understanding executors is essential for modeling realistic traffic:

Executor Controls Best For
shared-iterations Total iterations across all VUs Quick smoke tests
per-vu-iterations Iterations per VU Ensuring each VU runs N times
constant-vus Fixed VU count Steady-state testing
ramping-vus VU count over time Ramp-up/down patterns
constant-arrival-rate Fixed request rate SLO validation (RPS-based)
ramping-arrival-rate Request rate over time Finding the breaking point
externally-controlled Via REST API Dynamic load adjustment