﻿---
title: Threshold rules
description: Create threshold rules to alert when the number of matching events exceeds a specified count within a rule run.
url: https://www.elastic.co/elastic/docs-builder/docs/2948/solutions/security/detect-and-alert/threshold
products:
  - Elastic Cloud Serverless
  - Elastic Security
applies_to:
  - Serverless Security projects: Generally available
  - Elastic Stack: Generally available
---

# Threshold rules
Threshold rules search your Elasticsearch indices and generate an alert when the number of events matching a query meets or exceeds a specified threshold within a single rule execution. Optionally, events can be grouped by one or more fields so that each unique combination is evaluated independently.

### When to use a threshold rule

Threshold rules are the right fit when:
- You want to detect **volume-based anomalies**, such as a brute-force attack (many failed logins from a single source IP) or a data exfiltration attempt (an unusually high number of outbound connections).
- The signal is not a single event but a **count crossing a boundary** within a time window.
- You need to group counts by fields like `source.ip`, `user.name`, or `destination.ip` and alert on each group independently.

Threshold rules are **not** the best fit when:
- A single matching event is sufficient. Use a [custom query rule](https://www.elastic.co/elastic/docs-builder/docs/2948/solutions/security/detect-and-alert/custom-query) instead.
- You need to detect a specific **order** of events. Use an [EQL rule](https://www.elastic.co/elastic/docs-builder/docs/2948/solutions/security/detect-and-alert/eql) instead.
- You need full aggregation pipelines with transformations. Use an [ES|QL rule](https://www.elastic.co/elastic/docs-builder/docs/2948/solutions/security/detect-and-alert/esql) instead.


### Data requirements

Threshold rules require at least one Elasticsearch index pattern or data view. The data should contain the fields you plan to group by and enough event volume for meaningful threshold evaluation.

## Annotated examples

The following examples use the [detections API](https://www.elastic.co/elastic/docs-builder/docs/2948/solutions/security/detect-and-alert/using-the-api) request format to show how threshold rules are defined. Each example is followed by a breakdown of the threshold-specific fields. For common fields like `name`, `severity`, and `interval`, refer to the [detections API documentation](https://www.elastic.co/docs/api/doc/kibana/group/endpoint-detection-engine-rules-api).

### Brute-force detection with group by

This rule alerts when a single source IP generates 100 or more failed login attempts within a single rule execution window.
```json
{
  "type": "threshold",
  "language": "kuery",
  "name": "Brute-force login attempts by source IP",
  "description": "Alerts when a source IP produces 100 or more failed logins.",
  "query": "event.category: \"authentication\" and event.outcome: \"failure\"",
  "threshold": {
    "field": ["source.ip"],
    "value": 100
  },
  "index": ["filebeat-*", "logs-system.*", "winlogbeat-*"],
  "severity": "high",
  "risk_score": 73,
  "interval": "5m",
  "from": "now-6m"
}
```


| Field             | Value                                                           | Purpose                                                                                                                                                                                                     |
|-------------------|-----------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `type`            | `"threshold"`                                                   | Identifies this as a threshold rule.                                                                                                                                                                        |
| `query`           | `event.category: "authentication" and event.outcome: "failure"` | A KQL filter that selects the events to count. Only failed authentication events are counted against the threshold. Uses `"kuery"` or `"lucene"`, the same query languages available in custom query rules. |
| `threshold.field` | `["source.ip"]`                                                 | Groups events by source IP. Each unique IP is evaluated independently against the threshold. Accepts up to 5 fields, or an empty array `[]` to count all matching events together without grouping.         |
| `threshold.value` | `100`                                                           | The minimum event count required to generate an alert. Each source IP must produce at least 100 failed logins in a single rule execution window. Must be at least `1`.                                      |


### Port scan detection with cardinality constraint

This rule alerts when a source IP connects to many unique destination ports, indicating potential port scanning. The cardinality constraint ensures alerts fire only for connections across multiple ports, filtering out repeated connections to the same port.
```json
{
  "type": "threshold",
  "language": "kuery",
  "name": "Possible port scan detected",
  "description": "Alerts when a source IP connects to 25 or more unique destination ports.",
  "query": "event.category: \"network\" and event.type: \"connection\"",
  "threshold": {
    "field": ["source.ip"],
    "value": 50,
    "cardinality": [
      { "field": "destination.port", "value": 25 }
    ]
  },
  "index": ["packetbeat-*", "logs-endpoint.events.*"],
  "severity": "medium",
  "risk_score": 47,
  "interval": "5m",
  "from": "now-6m"
}
```


| Field                                 | Value                                            | Purpose                                                                                                                                                                                                                         |
|---------------------------------------|--------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `threshold.cardinality`               | `[{ "field": "destination.port", "value": 25 }]` | Adds a cardinality constraint. An alert fires only for source IPs that connect to at least 25 unique destination ports across 50 or more events. This filters out high-volume but benign repeated connections to the same port. |
| `threshold.field` + `threshold.value` | `["source.ip"]` / `50`                           | Groups by source IP and requires at least 50 matching events. Both the event count and the cardinality constraint must be met for an alert to fire.                                                                             |


## Threshold rule field reference

The following settings appear in the **Define rule** section when creating a threshold rule. For settings shared across all rule types, refer to [Rule settings reference](https://www.elastic.co/elastic/docs-builder/docs/2948/solutions/security/detect-and-alert/common-rule-settings).
<definitions>
  <definition term="Index patterns or data view">
    The Elasticsearch indices or data view the rule searches.
  </definition>
  <definition term="Custom query">
    The KQL or Lucene query used to filter events before counting. Only matching documents are evaluated against the threshold.
  </definition>
  <definition term="Group by (optional)">
    One or more fields to group events by. Each unique combination of field values is evaluated independently against the threshold.
    <applies-to>Elastic Stack: Generally available from 9.0 to 9.1</applies-to> You can specify up to 3 fields.
    <applies-to>Elastic Stack: Generally available since 9.2</applies-to> You can specify up to 5 fields.
  </definition>
  <definition term="Threshold">
    The minimum number of matching events required to generate an alert. If **Group by** is defined, each group must independently meet this count.
  </definition>
  <definition term="Count (optional)">
    A cardinality constraint on an additional field. Limits alerts to groups where the specified field has at least the given number of unique values.
  </definition>
  <definition term="Suppress alerts (optional)">
    Reduce repeated or duplicate alerts. For details, refer to [Alert suppression](https://www.elastic.co/elastic/docs-builder/docs/2948/solutions/security/detect-and-alert/alert-suppression).
  </definition>
</definitions>