PromQL limitations
PromQL reads metrics stored in time series data streams (TSDS).
The following constraints apply to execution in Elasticsearch, including the Prometheus-compatible HTTP API and the ES|QL PROMQL source command, unless stated otherwise.
They describe behavioral differences and unsupported areas compared with upstream Prometheus.
Routes that document POST accept parameters in an application/x-www-form-urlencoded body only when security is enabled, xpack.security.http.ssl.enabled is true on the Elasticsearch HTTP interface, and the request is authenticated.
TLS that terminates before Elasticsearch (plain HTTP to the node) does not satisfy this check.
Use GET with query-string parameters when POST is unavailable.
The PromQL HTTP API documents only the parameters each route accepts. Extra parameters from the Prometheus HTTP API are not supported yet. Elasticsearch does not ignore them: the request fails with 400 Bad Request. Configure clients and integrations to omit them.
/api/v1/query evaluates the expression at time. Selectors without a range look back a fixed five minutes for the latest sample, which matches the Prometheus default lookback delta.
Optional lookback_delta from the Prometheus API is not supported yet on this route. See Unsupported Prometheus query parameters and the query endpoint documentation.
/api/v1/query is implemented as a five-minute range query ending at time, returning the last sample per series.
When a scrape target disappears, Prometheus ingests staleness markers. Instant vector selectors then omit those series from instant-vector results, so metrics that stopped reporting do not appear as still current.
Elasticsearch does not apply Prometheus staleness markers yet. For now, a series stops appearing in results only once all its samples fall outside the evaluation window, rather than disappearing as soon as data stops arriving.
The majority of PromQL expressions run unchanged. The following constructs are not evaluated yet, so they return a client error (4xx):
- Binary set operators:
andandunless. -
Binary set operator or, except at the top level of an expression. A top-levelorchain supports at most 8 operands and can't useon(...)orignoring(...). A nestedor, a chain of more than 8 operands, or anorwithon(...)orignoring(...)returns a client error (4xx). - Comparison operators: evaluated only at the top level of an expression and only with a scalar literal on the right-hand side. Comparisons between two instant vectors, and nested comparisons, return a client error (4xx).
- Group modifiers:
on(...),ignoring(...),group_left,group_right. - The
@modifier. - Subqueries, such as
max_over_time(rate(http_requests_total)[1h:]). - Selectors without a metric name, and regex matchers on
__name__, such as{__name__=~"node_.*"}. - Binary expressions with a
without(...)aggregation as an operand, andwithout(...)aggregations nested inside anotherwithout(...)aggregation, such assum without (pod) (max without (container) (...)). Useby(...)instead. -
Binary expressions whose operands use different offsetvalues, such asrate(http_requests_total) / rate(http_requests_total offset 1h). This restriction doesn't apply toor. -
Binary expressions where both operands read metrics and one of them nests an aggregation inside another aggregation, such as count(count by (pod) (up)) / sum(machine_count). Nested aggregations on their own, such assum(sum by (pod) (...)), are supported. - Functions: refer to Not yet supported for the full list of recognized but unimplemented functions. Some supported functions have restrictions, which are listed under Differences from Prometheus on each function's reference entry.
-
Binary set operator or. -
The offsetmodifier.
The following constructs return no results instead of an error:
- Binary expressions between two operands that read different metrics without aggregating them, such as
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes. Unlike in Prometheus, the series of the two metrics aren't matched on their other labels. Aggregate both operands by the labels to keep instead, such asavg by (instance) (node_memory_MemAvailable_bytes) / avg by (instance) (node_memory_MemTotal_bytes).
Elasticsearch provides basic support for Prometheus native histograms (the exponential_histogram type in Elasticsearch).
The following query patterns work today:
histogram_quantileon native histograms, including after aggregation:histogram_quantile(0.9, sum by (job) (increase(metric)))histogram_count,histogram_sum,histogram_avg, andhistogram_fractionon native histograms increaseon native histogramssumaggregation on native histograms to aggregate across series
In particular, the following features are not available yet for native histograms:
rate: If possible, useincreaseinstead. Theratefunction produces fractional bucket counts that native histograms do not support yet. Most queries that useratecan be rewritten withincrease(for example,histogram_quantile(0.99, sum by (job) (increase(metric)))instead of usingrate).- Native histograms as direct result types: Queries that return a raw native histogram (such as a bare selector
my_histogramorincrease(my_histogram)without wrapping in a histogram function) are not supported. Wrap selectors inhistogram_quantile,histogram_count,histogram_sum,histogram_avg, orhistogram_fractionto obtain scalar results. irateanddelta- Arithmetic operators on native histograms:
+,-,*,/ histogram_stddev
On /api/v1/metadata, each metric includes a help string shaped like Prometheus HELP lines.
Metric definition help text is not surfaced yet, so the help field remains an empty string.
/api/v1/query_exemplars is not implemented yet, so exemplar queries are not supported.
To avoid errors, turn off exemplar queries in your Prometheus-compatible client.
In Grafana, go to Data sources → Elasticsearch → Exemplars and disable all configured exemplar links.
Time buckets align to fixed calendar boundaries rather than the query start time. This can cause slight differences from Prometheus, especially for short ranges or large step sizes.