Persistent breach detection in Kibana Universal Alerting
Elastic Cloud Serverless projects are autoscaled environments, fully managed by Elastic and available on Elastic Cloud. Availability This functionality is generally available and ready for production usage. Serverless interfaces and procedures might differ from classic Elastic Stack deployments. The Elastic Stack includes Elastic's core products such as Elasticsearch, Kibana, Logstash, and Beats. Availability We plan to add this functionality in a future Elastic Stack update. Subject to changes. Unless stated otherwise on the page, this functionality is available when your Elastic Stack is deployed on Elastic Cloud Hosted, Elastic Cloud Enterprise, Elastic Cloud on Kubernetes, and self-managed environments. This documentation corresponds to the latest patch available for each minor version. If you're not using the latest patch, check the release notes for changes.
Serverless
Generally available
Stack
Planned
Planned
A persistent breach condition in a Kibana Universal Alerting rule detects a metric that stays above a threshold across several consecutive time buckets, for example CPU above 90% in all 10 of the last 10 five-minute windows. This filters out transient spikes and fires only when a problem has been sustained.
ES|QL can express this with bucket counting:
FROM metrics-*
| WHERE @timestamp >= NOW() - 50 minutes
| EVAL bucket = BUCKET(@timestamp, 5 minutes)
| STATS
total_buckets = COUNT_DISTINCT(bucket),
exceeding_buckets = COUNT_DISTINCT(
CASE(system.cpu.total.pct > 0.90, bucket, null)
)
BY host.name
| WHERE total_buckets >= 10
AND exceeding_buckets == total_buckets
| KEEP host.name, total_buckets, exceeding_buckets
- Lookback must cover all 10 buckets (10 × 5 min = 50 min)
- Assign each event to its 5-minute time bucket
- How many distinct buckets exist in the window
- Count only buckets where CPU exceeded threshold;
- null values are excluded by COUNT_DISTINCT
- Require a full window of data before firing;
- every bucket must have breached
The rule's lookback window must cover all the buckets you want to check. In this example, 10 five-minute buckets requires at least 50 minutes of lookback.
If any bucket is missing because the host stopped reporting briefly mid-window, total_buckets drops below 10 and the condition doesn't fire. This is a deliberate safety check: a host that went silent for one bucket is treated as "we don't have enough data to confirm persistence" rather than "breach."
If you want to allow some gaps, replace exceeding_buckets == total_buckets with a ratio or a minimum count:
| WHERE total_buckets >= 8
AND exceeding_buckets >= total_buckets * 0.9
- Tolerate up to 2 missing buckets
- 90% of present buckets must have breached
Design the query so that gaps in reporting produce the behavior you want before deploying it.
- ES|QL query patterns: Browse query patterns ordered by complexity, from a basic event filter to SLO burn rate and persistent breach detection.
- Alert delay: A setting-based alternative for requiring consecutive breaches before an alert opens.