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 field-by-field breakdown.
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 (replacing a separate index field). 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. |
No index field |
— | ES|QL rules specify source indices in the FROM command rather than in a separate index field. |
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 are specific to ES|QL rules. 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.
- Required fields (optional)
- An informational list of fields the rule needs to function. This does not affect rule execution.
- Related integrations (optional)
- Associate the rule with one or more Elastic integrations to indicate data dependencies and allow users to verify each integration's installation status.