ES|QL rules
ES|QL rules use Elasticsearch Query Language (ES|QL) to query source events and aggregate or transform data using a pipeline syntax. Query results are returned as a table where each row becomes an alert. ES|QL rules combine the flexibility of a full query pipeline with the detection capabilities of Elastic Security.
ES|QL rules are the right fit when:
- You need aggregation, transformation, or enrichment within the query itself, such as computing statistics, renaming fields, or filtering on calculated values.
- The detection logic requires pipe-based processing that KQL and EQL cannot express, such as
STATS...BYfollowed byWHEREto filter aggregated results. - You want to create new computed fields (using
EVAL) and alert on values derived from source data rather than raw field values.
ES|QL rules are not the best fit when:
- A field-value match is sufficient. Use a custom query rule instead.
- You need to detect ordered event sequences. Use an EQL rule instead.
- You want anomaly detection without explicit query logic. Use a machine learning rule instead.
ES|QL rules query Elasticsearch indices directly using the FROM command. The indices must be accessible to the user who creates or last edits the rule.
The following examples use the detections API request format to show how ES|QL rules are defined. Each example is followed by a breakdown of the ES|QL-specific fields. For common fields like name, severity, and interval, refer to the detections API documentation.
This rule counts failed login attempts per user and alerts when any user exceeds 20 failures within the query window.
{
"type": "esql",
"language": "esql",
"name": "High failed login count per user",
"description": "Detects users with more than 20 failed login attempts in the query window.",
"query": "FROM logs-* | WHERE event.category == \"authentication\" AND event.outcome == \"failure\" | STATS failed_count = COUNT(*) BY user.name | WHERE failed_count > 20",
"severity": "high",
"risk_score": 73,
"interval": "5m",
"from": "now-6m"
}
| Field | Value | Purpose |
|---|---|---|
type / language |
"esql" / "esql" |
Both must be "esql". |
query |
FROM logs-* \| WHERE ... \| STATS ... BY ... \| WHERE ... |
An aggregating query pipeline. FROM specifies the source indices. STATS...BY groups failed logins by user.name and counts them. The final WHERE filters to users exceeding 20 failures. Each result row becomes an alert containing only the BY fields and computed values. |
ES|QL rules don't use a separate index field. Source indices are specified in the FROM command within the query.
This rule detects process-start events with suspicious encoded arguments and uses METADATA to enable alert deduplication across rule executions.
{
"type": "esql",
"language": "esql",
"name": "Process execution with encoded arguments",
"description": "Detects process start events where the command line contains encoded content.",
"query": "FROM logs-endpoint.events.* METADATA _id, _index, _version | WHERE event.category == \"process\" AND event.type == \"start\" AND process.command_line LIKE \"*-encoded*\" | LIMIT 100",
"severity": "medium",
"risk_score": 47,
"interval": "5m",
"from": "now-6m"
}
| Field | Value | Purpose |
|---|---|---|
query |
FROM ... METADATA _id, _index, _version \| WHERE ... \| LIMIT 100 |
A non-aggregating query. METADATA _id, _index, _version after FROM enables alert deduplication so the same source event does not generate duplicate alerts across rule executions. Without it, repeated matches produce repeated alerts. |
LIMIT |
100 |
Caps the number of results per execution. Interacts with the Max alerts per run setting, and the rule uses the lower of the two values. |
The following settings appear in the Define rule section when creating an ES|QL rule. For settings shared across all rule types, refer to Rule settings reference.
- ES|QL query
- The ES|QL query that defines the detection logic. Can be aggregating (with
STATS...BY) or non-aggregating. Each row in the query result becomes an alert. - Suppress alerts by (optional)
- Reduce repeated or duplicate alerts by grouping them on one or more fields. For details, refer to Alert suppression.