Skip to main content
Metrics measure how your system performs under load. k6 automatically collects built-in metrics and lets you create custom metrics for application-specific measurements.

What are metrics?

Metrics are measurements that k6 collects during test execution. They provide quantitative data about:
  • Request rates and response times
  • Error rates and status codes
  • Data transfer and connection times
  • Custom application-specific measurements
k6 uses these metrics to generate test results, evaluate thresholds, and help you identify performance issues.

The four metric types

k6 organizes metrics into four types, each suited for different measurements:
Counters sum values over time.Use for: Total number of requests, errors, or events
import { Counter } from 'k6/metrics';

const errors = new Counter('errors');

export default function () {
  if (someCondition) {
    errors.add(1);
  }
}

Built-in metrics

k6 automatically collects metrics for HTTP requests and test execution. You don’t need to do anything to collect these.

The RED metrics

The most important metrics follow the RED method (Requests, Errors, Duration):

http_reqs

RequestsTotal number of HTTP requests

http_req_failed

ErrorsRate of failed requests

http_req_duration

DurationRequest response time
These three metrics provide a comprehensive view of your system’s performance and should be your starting point for analysis.

Other HTTP metrics

k6 also collects detailed HTTP timing metrics:
MetricDescription
http_req_blockedTime waiting for available TCP connection
http_req_connectingTime establishing TCP connection
http_req_tls_handshakingTime for TLS handshake
http_req_sendingTime sending data
http_req_waitingTime waiting for response (TTFB)
http_req_receivingTime receiving response
data_sentAmount of data sent
data_receivedAmount of data received

Execution metrics

MetricDescription
iterationsTotal number of VU iterations
iteration_durationTime to complete one iteration
vusCurrent number of active VUs
vus_maxMaximum VUs allocated

Example output

When you run a test, k6 displays metrics in the end-of-test summary:
$ k6 run script.js

 TOTAL RESULTS

    HTTP
    http_req_duration..........: avg=117.55ms min=117.55ms med=117.55ms max=117.55ms p(90)=117.55ms p(95)=117.55ms
      { expected_response:true }: avg=117.55ms min=117.55ms med=117.55ms max=117.55ms p(90)=117.55ms p(95)=117.55ms
    http_req_failed............: 0.00%  0 out of 1
    http_reqs..................: 1      2.768749/s

    EXECUTION
    iteration_duration.........: avg=361.09ms min=361.09ms med=361.09ms max=361.09ms p(90)=361.09ms p(95)=361.09ms
    iterations.................: 1      2.768749/s

    NETWORK
    data_received..............: 6.8 kB 19 kB/s
    data_sent..................: 541 B  1.5 kB/s

Creating custom metrics

Create custom metrics to measure application-specific performance.
Custom metrics must be created in init context (outside lifecycle functions). This ensures k6 can validate thresholds and manage memory efficiently.

Basic pattern

1

Import the metric type

import { Trend } from 'k6/metrics';
2

Create the metric in init context

const myTrend = new Trend('waiting_time');
3

Add measurements in VU code

export default function () {
  const res = http.get('https://test.k6.io');
  myTrend.add(res.timings.waiting);
}

Custom metric examples

import http from 'k6/http';
import { Trend } from 'k6/metrics';

const waitingTime = new Trend('waiting_time');

export default function () {
  const res = http.get('https://quickpizza.grafana.com/');
  waitingTime.add(res.timings.waiting);
}

Custom metric output

Custom metrics appear in the end-of-test summary with their aggregated values:
$ k6 run script.js

  ...
  iteration_duration.............: avg=1.15s    min=1.15s    med=1.15s    max=1.15s
  iterations.....................: 1     0.864973/s
  waiting_time...................: avg=265.25ms min=265.25ms med=265.25ms max=265.25ms
Custom metrics are collected at the end of each VU iteration. For long-running tests, metrics might not appear until the first iteration completes.

Tagging custom metrics

Add tags to custom metric values for filtering:
import http from 'k6/http';
import { Trend } from 'k6/metrics';

const apiDuration = new Trend('api_duration');

export default function () {
  const res = http.get('https://quickpizza.grafana.com/api/pizzas');
  
  // Add metric value with tags
  apiDuration.add(res.timings.duration, {
    endpoint: '/api/pizzas',
    status: res.status,
  });
}

Thresholds on custom metrics

Set pass/fail criteria for custom metrics:
import http from 'k6/http';
import { Trend } from 'k6/metrics';

const waitingTime = new Trend('waiting_time');

export const options = {
  thresholds: {
    waiting_time: ['p(95)<300', 'avg<200'],
  },
};

export default function () {
  const res = http.get('https://quickpizza.grafana.com/');
  waitingTime.add(res.timings.waiting);
}

Complete example

Here’s a comprehensive example using all four metric types:
import http from 'k6/http';
import { sleep } from 'k6';
import { Counter, Gauge, Rate, Trend } from 'k6/metrics';

// Custom metrics
const apiCalls = new Counter('api_calls');
const responseSize = new Gauge('response_size');
const successRate = new Rate('success_rate');
const apiDuration = new Trend('api_duration');

export const options = {
  vus: 10,
  duration: '30s',
  thresholds: {
    api_calls: ['count>100'],
    response_size: ['value<10000'],
    success_rate: ['rate>0.95'],
    api_duration: ['p(95)<500'],
  },
};

export default function () {
  const res = http.get('https://quickpizza.grafana.com/api/pizzas');
  
  // Record measurements
  apiCalls.add(1);
  responseSize.add(res.body.length);
  successRate.add(res.status === 200);
  apiDuration.add(res.timings.duration);
  
  sleep(1);
}

Metric name restrictions

Metric names must:
  • Contain only ASCII letters, numbers, and underscores
  • Start with a letter or underscore
  • Be 128 characters or less
// Valid
const myMetric = new Trend('api_response_time');
const anotherMetric = new Counter('_total_requests');

// Invalid
const invalid1 = new Trend('123-metric');  // Starts with number
const invalid2 = new Trend('my-metric');   // Contains hyphen

Best practices

Start with RED metrics

Monitor http_reqs, http_req_failed, and http_req_duration before diving into custom metrics.

Choose the right type

Use Trend for durations, Rate for percentages, Counter for totals, Gauge for current values.

Tag for analysis

Add tags to metrics to enable filtering by endpoint, status, or other dimensions.

Set thresholds

Define thresholds on metrics to automate pass/fail decisions.

Next steps

Metrics Reference

Complete list of all built-in metrics

Thresholds

Set pass/fail criteria using metrics

Build docs developers (and LLMs) love