> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/grafana/k6/llms.txt
> Use this file to discover all available pages before exploring further.

# Thresholds

> Define pass/fail criteria for your k6 tests using thresholds.

Thresholds are pass/fail criteria for your load tests. They specify the acceptable limits for your metrics, allowing you to automate test evaluation.

## What are Thresholds?

From `metrics/thresholds.go`, thresholds are expressions that evaluate metric values against defined criteria. If a threshold fails, k6 exits with a non-zero status code.

```javascript theme={null}
import http from 'k6/http';

export const options = {
  thresholds: {
    // 95th percentile response time must be below 500ms
    http_req_duration: ['p(95)<500'],
    
    // Less than 1% of requests can fail
    http_req_failed: ['rate<0.01'],
  },
};

export default function() {
  http.get('https://quickpizza.grafana.com/');
}
```

When thresholds fail, k6 exits with code 99 (from `errext/exitcodes`).

## Threshold Syntax

From `metrics/thresholds_parser.go`, threshold expressions follow this format:

```
aggregationMethod(value) operator value
```

### Supported Operators

From `metrics/thresholds.go`, the `run()` function supports:

* `>` - Greater than
* `>=` - Greater than or equal
* `<` - Less than
* `<=` - Less than or equal
* `==` or `===` - Equal to
* `!=` - Not equal to

### Examples

```javascript theme={null}
export const options = {
  thresholds: {
    http_req_duration: ['p(95)<500'],        // 95th percentile < 500ms
    http_req_duration: ['avg<200'],          // Average < 200ms
    http_req_duration: ['max<2000'],         // Maximum < 2s
    http_req_duration: ['med<150'],          // Median < 150ms
    http_req_failed: ['rate<0.01'],          // Error rate < 1%
    http_reqs: ['count>100'],                // At least 100 requests
    checks: ['rate>0.95'],                   // 95% of checks pass
  },
};
```

## Aggregation Methods by Metric Type

From `metrics/metric_type.go`, each metric type supports specific aggregation methods:

### Counter Metrics

**Supported methods:** `count`, `rate`

```javascript theme={null}
export const options = {
  thresholds: {
    http_reqs: ['count>1000'],               // Total requests > 1000
    http_reqs: ['rate>50'],                  // Request rate > 50/sec
    iterations: ['count>=500'],              // At least 500 iterations
  },
};
```

### Gauge Metrics

**Supported methods:** `value`

```javascript theme={null}
export const options = {
  thresholds: {
    vus: ['value>10'],                       // VUs > 10
    vus_max: ['value<=100'],                 // Max VUs ≤ 100
  },
};
```

### Trend Metrics

**Supported methods:** `avg`, `min`, `max`, `med`, `p(N)`

```javascript theme={null}
export const options = {
  thresholds: {
    http_req_duration: [
      'avg<200',                             // Average < 200ms
      'min<50',                              // Minimum < 50ms  
      'max<1000',                            // Maximum < 1s
      'med<150',                             // Median < 150ms
      'p(90)<400',                           // 90th percentile < 400ms
      'p(95)<500',                           // 95th percentile < 500ms
      'p(99)<800',                           // 99th percentile < 800ms
      'p(99.9)<1000',                        // 99.9th percentile < 1s
    ],
    iteration_duration: ['p(95)<5000'],      // 95% complete in 5s
  },
};
```

### Rate Metrics

**Supported methods:** `rate`

```javascript theme={null}
export const options = {
  thresholds: {
    checks: ['rate>0.95'],                   // 95% success rate
    http_req_failed: ['rate<0.01'],          // < 1% failures
  },
};
```

## Multiple Thresholds

Define multiple thresholds for the same metric from `examples/thresholds.js`:

```javascript theme={null}
export const options = {
  thresholds: {
    http_req_duration: [
      'p(95)<500',    // First threshold
      'p(99)<1000',   // Second threshold
      'max<2000',     // Third threshold
    ],
  },
};
```

All thresholds must pass for the test to succeed.

## Thresholds on Tagged Metrics

From `examples/thresholds.js`, filter metrics by tags:

```javascript theme={null}
export const options = {
  thresholds: {
    // Threshold for all requests
    'http_req_duration': ['p(95)<500'],
    
    // Threshold for specific URL
    'http_req_duration{name:http://httpbin.org/post}': ['max<1000'],
    
    // Threshold for custom tag
    'http_req_duration{staticAsset:yes}': ['p(99)<500'],
  },
};

export default function() {
  http.get('https://quickpizza.grafana.com/');
  http.post('https://quickpizza.grafana.com/post', {data: 'some data'});
  
  http.get('https://quickpizza.grafana.com/style.css', {
    tags: { staticAsset: 'yes' },
  });
}
```

## Aborting on Threshold Failure

From `metrics/thresholds.go`, use `abortOnFail` to stop tests immediately when a threshold fails:

```javascript theme={null}
export const options = {
  thresholds: {
    http_req_failed: [
      // Normal threshold
      'rate<0.01',
      
      // Abort if error rate exceeds 5%
      { threshold: 'rate<=0.05', abortOnFail: true },
    ],
  },
};
```

From the source code:

* When `abortOnFail` is true and the threshold fails, `ts.Abort` is set
* The test terminates early
* Useful for preventing wasted test time when critical issues occur

### Abort Grace Period

From `metrics/thresholds.go`, delay abort to allow test startup:

```javascript theme={null}
export const options = {
  thresholds: {
    http_req_failed: [
      {
        threshold: 'rate<=0.05',
        abortOnFail: true,
        delayAbortEval: '1m',  // Don't abort for first minute
      },
    ],
  },
};
```

<Note>
  Grace periods prevent false positives during test ramp-up when metrics may be unstable.
</Note>

## Real-World Example

From `examples/thresholds_readme_example.js`:

```javascript theme={null}
import http from 'k6/http';
import { check, group, sleep } from 'k6';
import { Rate } from 'k6/metrics';

// Custom metric to track failure rates
const failureRate = new Rate('check_failure_rate');

export const options = {
  stages: [
    { target: 50, duration: '1m' },
    { target: 50, duration: '3m30s' },
    { target: 0, duration: '30s' },
  ],
  thresholds: {
    // 95th percentile of all requests < 750ms
    'http_req_duration': ['p(95)<750'],
    
    // Static assets finish faster
    'http_req_duration{staticAsset:yes}': ['p(99)<500'],
    
    // Custom metric thresholds
    'check_failure_rate': [
      // Global failure rate < 1%
      'rate<0.01',
      
      // Abort if it exceeds 5%
      { threshold: 'rate<=0.05', abortOnFail: true },
    ],
  },
};

export default function () {
  const response = http.get('https://quickpizza.grafana.com/test.k6.io/');

  const checkRes = check(response, {
    'http2 is used': (r) => r.proto === 'HTTP/2.0',
    'status is 200': (r) => r.status === 200,
    'content is present': (r) => r.body.indexOf('This is a replacement') !== -1,
  });

  // Track failures
  failureRate.add(!checkRes);

  // Load static assets
  group('Static Assets', function () {
    const resps = http.batch([
      ['GET', 'https://quickpizza.grafana.com/test.k6.io/static/css/site.css', 
       null, { tags: { staticAsset: 'yes' } }],
      ['GET', 'https://quickpizza.grafana.com/test.k6.io/static/favicon.ico', 
       null, { tags: { staticAsset: 'yes' } }],
    ]);
    
    failureRate.add(!check(resps, {
      'status is 200': (r) => r[0].status === 200 && r[1].status === 200,
    }));
  });

  sleep(Math.random() * 3 + 2);
}
```

## Threshold Validation

From `metrics/thresholds.go`, the `Validate()` function ensures:

1. The metric exists in the registry
2. The aggregation method is supported for the metric type
3. The threshold expression is syntactically correct

Invalid thresholds cause k6 to exit with `exitcodes.InvalidConfig`.

### Common Validation Errors

```javascript theme={null}
export const options = {
  thresholds: {
    // ❌ ERROR: 'avg' not supported for Counter
    http_reqs: ['avg<100'],
    
    // ❌ ERROR: 'count' not supported for Rate  
    checks: ['count>50'],
    
    // ✅ CORRECT: 'rate' supported for Rate
    checks: ['rate>0.95'],
    
    // ✅ CORRECT: 'count' supported for Counter
    http_reqs: ['count>100'],
  },
};
```

## Threshold Execution

From `metrics/thresholds.go`, the `Run()` method:

1. Collects sink values (aggregated metrics)
2. Evaluates each threshold expression
3. Sets `LastFailed` flag on failing thresholds
4. Determines if test should abort

### Sink Values

From `metrics/thresholds.go`, different sinks provide different values:

**CounterSink:**

* `count` - Total value
* `rate` - Value per second

**GaugeSink:**

* `value` - Current value

**TrendSink:**

* `min`, `max`, `avg`, `med` - Statistics
* `p(N)` - Percentiles (calculated on demand)

**RateSink:**

* `rate` - Ratio of true values to total

## Thresholds in CI/CD

Thresholds make k6 tests suitable for automated pipelines:

```bash theme={null}
# Run test
k6 run test.js

# Check exit code
if [ $? -eq 0 ]; then
  echo "Test passed!"
else
  echo "Test failed - thresholds not met"
  exit 1
fi
```

### Exit Codes

* `0` - All thresholds passed
* `99` - One or more thresholds failed (from `errext/exitcodes`)
* Other codes indicate different errors

## Best Practices

<Steps>
  <Step title="Start Conservative">
    Begin with loose thresholds and tighten them as you understand system behavior.
  </Step>

  <Step title="Focus on Percentiles">
    Use p(95) or p(99) instead of averages to catch outliers.
  </Step>

  <Step title="Set Multiple Thresholds">
    Define thresholds for different aspects: latency, error rate, throughput.
  </Step>

  <Step title="Use Tags for Granularity">
    Apply different thresholds to different request types or endpoints.
  </Step>

  <Step title="Add Abort Conditions">
    Use `abortOnFail` for critical failures to save resources.
  </Step>
</Steps>

<Warning>
  Too strict thresholds cause false failures. Base thresholds on realistic performance expectations.
</Warning>

<Tip>
  Combine thresholds with custom metrics to track business-specific SLOs (Service Level Objectives).
</Tip>

## Common Threshold Patterns

### API Performance SLO

```javascript theme={null}
export const options = {
  thresholds: {
    http_req_duration: ['p(99)<1000', 'p(95)<500'],
    http_req_failed: ['rate<0.001'],  // 99.9% success
    http_reqs: ['rate>10'],           // Minimum throughput
  },
};
```

### Multi-Environment Thresholds

```javascript theme={null}
const thresholds = __ENV.ENV === 'prod' 
  ? { http_req_duration: ['p(95)<200'] }      // Strict for production
  : { http_req_duration: ['p(95)<1000'] };    // Relaxed for staging

export const options = { thresholds };
```

### Progressive Thresholds

```javascript theme={null}
export const options = {
  thresholds: {
    // Must meet all of these
    http_req_duration: [
      'p(50)<100',   // Half of requests < 100ms
      'p(90)<300',   // 90% < 300ms
      'p(95)<500',   // 95% < 500ms
      'p(99)<1000',  // 99% < 1s
    ],
  },
};
```

Thresholds transform k6 from a measurement tool into an automated testing framework, enabling continuous performance validation in your development pipeline.
