﻿---
title: Prometheus compatibility
description: How PromQL in Elasticsearch differs from Prometheus, including unsupported constructs, evaluation differences, and HTTP API constraints.
url: https://www.elastic.co/elastic/docs-builder/docs/4268/reference/query-languages/promql/prometheus-compatibility
products:
  - Elasticsearch
applies_to:
  - Elastic Cloud Serverless: Generally available
  - Elastic Stack: Generally available since 9.5, Preview in 9.4
---

# Prometheus compatibility
PromQL in Elasticsearch reads metrics stored in [time series data streams](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4268/manage-data/data-store/data-streams/time-series-data-stream-tsds) (TSDS).
Most PromQL queries run unchanged and return the same results as Prometheus 3.x.
This page lists the PromQL features Elasticsearch doesn't support yet and where its behavior differs by design, so you can tell in advance whether a query runs and what it returns.
It applies to both the [Prometheus-compatible HTTP API](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/query-languages/promql/promql-http-api) and the ES|QL [`PROMQL`](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/query-languages/esql/commands/promql) source command, unless a section says otherwise.
The following sections follow the [Prometheus querying documentation](https://prometheus.io/docs/prometheus/latest/querying/basics/), so each difference sits under the heading that documents the construct in Prometheus.
Each section has up to three parts:
- **Supported**: what runs and returns the same result as in Prometheus.
- **Not supported yet**: Elasticsearch rejects the query with an error. Prometheus supports every construct in these tables, some only with a feature flag.
- **Behaves differently**: the query runs in both, but the result differs.

Rows link the issue that tracks the work, where there is one.
A row with a version badge applies only to those versions. A row without one applies to every version.

## Basics

Sections follow [Querying basics](https://prometheus.io/docs/prometheus/latest/querying/basics/) in the Prometheus documentation.

### Histograms

In the examples on this page, `h` is a native histogram metric.
**Supported**
<applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> Native histograms, stored as `exponential_histogram` fields.
`histogram_quantile`, `histogram_count`, `histogram_sum`, `histogram_avg`, `increase`, and `sum` support them, such as `histogram_quantile(0.9, sum by (job) (increase(h[5m])))`.
<applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> `histogram_fraction` and `changes` support them too.
Classic histograms, stored as `_bucket` series with an `le` label, such as `histogram_quantile(0.9, sum by (le) (rate(x_bucket[5m])))`.
**Not supported yet**
<table>
  | #   | Construct                                                                                                                                                                   | Example                | Workaround                                                 | Issue                                                             |
  |-----|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|------------------------------------------------------------|-------------------------------------------------------------------|
  | 1   | Native histogram as the result <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> | `h`, `increase(h[5m])` | Wrap it in a histogram function, such as `histogram_count` | [#152263](https://github.com/elastic/elasticsearch/issues/152263) |
</table>


### Range vector

**Supported**
Range vectors as function arguments, such as `rate(x[5m])`.
In the `PROMQL` command, the range can be left out, such as `rate(x)`.
Refer to [Implicit range selectors](/elastic/docs-builder/docs/4268/reference/query-languages/esql/commands/promql#esql-promql-implicit-range-selectors).
**Not supported yet**
<table>
  | #   | Construct                                      | Example | Workaround | Issue                                                             |
  |-----|------------------------------------------------|---------|------------|-------------------------------------------------------------------|
  | 2   | Range vector as the result of an instant query | `x[5m]` | -          | [#164220](https://github.com/elastic/elasticsearch/issues/164220) |
</table>


### Literals

**Supported**
String literals in single quotes, double quotes, or backticks.
Float literals, including scientific notation, hexadecimal, `Inf`, and `NaN`, such as `1e3` and `0x1f`.
Time durations, such as `1h30m`, and duration arithmetic, such as `x[5m + 1m]`.
**Not supported yet**
<table>
  | #   | Construct                                                                                                       | Example                              | Workaround           | Issue                                                             |
  |-----|-----------------------------------------------------------------------------------------------------------------|--------------------------------------|----------------------|-------------------------------------------------------------------|
  | 3   | `step()`, `range()`, `min_of()`, and `max_of()` in a duration (Prometheus: `promql-duration-expr` feature flag) | `x[step()]`, `x[min_of(5m, step())]` | Use a fixed duration | [#164221](https://github.com/elastic/elasticsearch/issues/164221) |
</table>


### Time series selectors


#### Instant vector selectors

**Supported**
A metric name with the label matchers `=`, `!=`, `=~`, and `!~`, such as `http_requests_total{job="api", code=~"5.."}`.
**Not supported yet**
<table>
  | #   | Construct                      | Example                 | Workaround                                            | Issue                                                             |
  |-----|--------------------------------|-------------------------|-------------------------------------------------------|-------------------------------------------------------------------|
  | 4   | Selector without a metric name | `{job="api"}`           | -                                                     | [#146977](https://github.com/elastic/elasticsearch/issues/146977) |
  | 5   | Regex matcher on `__name__`    | `{__name__=~"node_.*"}` | Combine the metrics with `or`: `node_cpu or node_mem` | [#146977](https://github.com/elastic/elasticsearch/issues/146977) |
</table>

**Behaves differently**
<table>
  | #   | Construct                      | Example                        | Elasticsearch | Prometheus                  | Issue                                                             |
  |-----|--------------------------------|--------------------------------|---------------|-----------------------------|-------------------------------------------------------------------|
  | 6   | Negative matcher on `__name__` | `{__name__!="up", job="node"}` | No results    | Every other matching metric | [#146977](https://github.com/elastic/elasticsearch/issues/146977) |
</table>


#### Range vector selectors

**Supported**
A range selector with a duration, such as `x[5m]` or `x[1h30m]`.
**Not supported yet**
<table>
  | #   | Construct                                                                                        | Example                    | Workaround | Issue                                                             |
  |-----|--------------------------------------------------------------------------------------------------|----------------------------|------------|-------------------------------------------------------------------|
  | 7   | `anchored` and `smoothed` modifiers (Prometheus: `promql-extended-range-selectors` feature flag) | `increase(x[5m] anchored)` | -          | [#164222](https://github.com/elastic/elasticsearch/issues/164222) |
</table>


#### Offset modifier

**Supported**
<applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> `offset` on instant and range selectors, such as `x offset 5m` and `rate(x[5m] offset 1h)`.
**Behaves differently**
<table>
  | #   | Construct                                     | Example        | Elasticsearch                                                       | Prometheus                        | Issue |
  |-----|-----------------------------------------------|----------------|---------------------------------------------------------------------|-----------------------------------|-------|
  | 8   | Negative offset at the end of the query range | `x offset -5m` | No value at the last steps. Samples after the query end aren't read | Reads samples after the query end | -     |
</table>


#### @ modifier

**Not supported yet**
<table>
  | #   | Construct    | Example                       | Workaround | Issue                                                             |
  |-----|--------------|-------------------------------|------------|-------------------------------------------------------------------|
  | 9   | `@` modifier | `x @ 1700000000`, `x @ end()` | -          | [#164139](https://github.com/elastic/elasticsearch/issues/164139) |
</table>


### Subquery

**Not supported yet**
<table>
  | #   | Construct | Example                             | Workaround | Issue                                                             |
  |-----|-----------|-------------------------------------|------------|-------------------------------------------------------------------|
  | 10  | Subquery  | `max_over_time(rate(x[5m])[1h:1m])` | -          | [#164139](https://github.com/elastic/elasticsearch/issues/164139) |
</table>


### Gotchas


#### Staleness

**Supported**
A selector without a range, such as `http_requests_total`, returns the latest sample of each series within the lookback window at each evaluation time.
**Behaves differently**
<table>
  | #   | Construct                   | Example               | Elasticsearch                                                            | Prometheus                                                  | Issue                                                             |
  |-----|-----------------------------|-----------------------|--------------------------------------------------------------------------|-------------------------------------------------------------|-------------------------------------------------------------------|
  | 11  | Lookback in instant queries | `/api/v1/query`       | Five minutes, fixed                                                      | Five minutes by default, configurable with `lookback_delta` | [#149939](https://github.com/elastic/elasticsearch/issues/149939) |
  | 12  | Lookback in range queries   | `/api/v1/query_range` | One `step`. A series disappears at the first step without its own sample | Five minutes. The last sample repeats until then            | -                                                                 |
  | 13  | Staleness markers           | -                     | Ignored. A series disappears once its samples leave the lookback window  | A series disappears at its staleness marker                 | -                                                                 |
</table>


## Operators

Sections follow [Operators](https://prometheus.io/docs/prometheus/latest/querying/operators/) in the Prometheus documentation.
Each [operator reference entry](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/query-languages/promql/operators) lists further differences.

### Binary operators


#### Arithmetic binary operators

**Supported**
`+`, `-`, `*`, `/`, `%`, and `^` between scalars, between an instant vector and a scalar, such as `rate(x[5m]) * 60`, and between two instant vectors.
[Vector matching](#prometheus-compatibility-vector-matching) lists which pairs of instant vectors match.
**Not supported yet**
<table>
  | #   | Construct                                                                                                                                                              | Example            | Workaround | Issue                                                             |
  |-----|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|------------|-------------------------------------------------------------------|
  | 14  | Native histogram operands <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> | `h * 2`, `h1 + h2` | -          | [#152263](https://github.com/elastic/elasticsearch/issues/152263) |
</table>


#### Trigonometric binary operators

**Not supported yet**
<table>
  | #   | Construct | Example     | Workaround | Issue                                                             |
  |-----|-----------|-------------|------------|-------------------------------------------------------------------|
  | 15  | `atan2`   | `x atan2 y` | -          | [#164153](https://github.com/elastic/elasticsearch/issues/164153) |
</table>


#### Comparison binary operators

**Supported**
`==`, `!=`, `>`, `<`, `>=`, and `<=` between an instant vector and a number, such as `rate(x[5m]) > 100`, with or without `bool`, such as `x > bool 100`.
**Not supported yet**
<table>
  | #   | Construct                                                 | Example                           | Workaround                                    | Issue                                                             |
  |-----|-----------------------------------------------------------|-----------------------------------|-----------------------------------------------|-------------------------------------------------------------------|
  | 16  | Filter with a scalar as the first operand                 | `100 < x`, `time() <= x`          | Swap the operands: `x > 100`                  | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 17  | Non-literal scalar as the second operand                  | `x > time()`, `x > scalar(y)`     | -                                             | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 18  | Two vectors, or `bool` with a scalar as the first operand | `x > y`, `100 > bool x`           | For `bool`, swap the operands: `x < bool 100` | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 19  | Comparison inside another expression                      | `(x > 100) + 1`, `count(x > 100)` | -                                             | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
</table>


#### Logical/set binary operators

**Supported**
<applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> `or` between instant vectors, such as `rate(a[5m]) or rate(b[5m])`.
An `or` chain takes at most 8 operands by default.
<applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> Change the limit with the `esql.query.max_branch_count_per_merge` cluster setting.
**Not supported yet**
<table>
  | #   | Construct                              | Example                                   | Workaround | Issue                                                             |
  |-----|----------------------------------------|-------------------------------------------|------------|-------------------------------------------------------------------|
  | 20  | `and`, `unless`                        | `a and b`, `a unless b`                   | -          | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 21  | `or` with `on(...)` or `ignoring(...)` | `a or on(job) b`                          | -          | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 22  | `or` inside another expression         | `(sum(a) or sum(b)) * 2`, `count(a or b)` | -          | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
</table>


### Vector matching

**Supported**
Arithmetic between unaggregated metrics stored together in the same time series, such as `network.bytes_in / network.connections`, without explicit vector matching modifiers.
Arithmetic between operands aggregated without grouping, such as `sum(a) / sum(b)`.
<applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> One-to-one, many-to-one, and one-to-many matching between operands aggregated with `by(...)`, including `on`, `ignoring`, `group_left`, and `group_right`.
For example: `sum by (instance) (a) / on(instance) sum by (instance) (b)`.
**Not supported yet**
<table>
  | #   | Construct                                                                                                                                                                                                                                                       | Example                                                | Workaround                                                                                               | Issue                                                             |
  |-----|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|----------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------|
  | 23  | Different unaggregated metrics stored as separate series with a `__name__` dimension, such as data ingested with Prometheus remote write <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> | `a / b`                                                | Aggregate both by the labels to match on: `sum by (instance) (a) / sum by (instance) (b)`                | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 24  | `on`, `ignoring`, `group_left`, or `group_right` with an operand that isn't aggregated                                                                                                                                                                          | `a / on(instance) b`, `a * on(pod) group_left(node) b` | Aggregate both operands by the labels to match on                                                        | [#157669](https://github.com/elastic/elasticsearch/issues/157669) |
  | 25  | Operands aggregated differently <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                                                    | `sum(a) / b`, `b / scalar(sum(a))`, `topk(2, a) * b`   | Aggregate both operands alike: `sum(a) / sum(b)`. A number, such as `sum(a) * 2`, and `or` are supported | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 26  | Nested aggregation next to an operand that reads a metric <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                          | `count(count by (pod) (a)) / sum(b)`                   | -                                                                                                        | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 27  | A different `offset` per operand <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                                                   | `rate(x[5m]) / rate(x[5m] offset 1h)`                  | `or` is supported                                                                                        | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
  | 28  | `label_replace` or `label_join` as an operand                                                                                                                                                                                                                   | `label_replace(a, ...) * on(pod) group_left(node) b`   | -                                                                                                        | [#157672](https://github.com/elastic/elasticsearch/issues/157672) |
  | 29  | `fill()`, `fill_left()`, and `fill_right()` (Prometheus: `promql-binop-fill-modifiers` feature flag)                                                                                                                                                            | `a + fill(0) b`                                        | -                                                                                                        | [#164223](https://github.com/elastic/elasticsearch/issues/164223) |
</table>

**Behaves differently**
<table>
  | #   | Construct                                                                                                                                                  | Example | Elasticsearch | Prometheus                           | Issue                                                             |
  |-----|------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|---------------|--------------------------------------|-------------------------------------------------------------------|
  | 30  | Different unaggregated metrics stored as separate series <applies-to>Elastic Stack: Generally available in 9.5, Elastic Stack: Preview in 9.4</applies-to> | `a / b` | No results    | Series matched on their other labels | [#158184](https://github.com/elastic/elasticsearch/issues/158184) |
</table>


### Aggregation operators

**Supported**
- `sum`, `avg`, `min`, `max`, `count`, `quantile`, `stddev`, and `stdvar`, with `by(...)`, `without(...)`, or no grouping.
- <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> `topk`, `bottomk`, `limitk`, and `limit_ratio`.

**Not supported yet**
<table>
  | #   | Construct                                                         | Example                                           | Workaround                                         | Issue                                                                                                                                |
  |-----|-------------------------------------------------------------------|---------------------------------------------------|----------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
  | 31  | `group`, `count_values`                                           | `group by (job) (x)`, `count_values("v", x)`      | -                                                  | [#164009](https://github.com/elastic/elasticsearch/issues/164009), [#136248](https://github.com/elastic/elasticsearch/issues/136248) |
  | 32  | `topk`, `bottomk`, `limitk`, or `limit_ratio` with `without(...)` | `topk without (instance) (1, x)`                  | Use `by(...)`                                      | [#157671](https://github.com/elastic/elasticsearch/issues/157671)                                                                    |
  | 33  | Parameter that isn't a number literal                             | `topk(scalar(a), b)`, `quantile(scalar(a), b)`    | Use a number                                       | [#164225](https://github.com/elastic/elasticsearch/issues/164225)                                                                    |
  | 34  | Nested `without(...)`                                             | `sum without (pod) (max without (container) (x))` | Use `by(...)`                                      | [#157671](https://github.com/elastic/elasticsearch/issues/157671)                                                                    |
  | 35  | `without(...)` as an operand                                      | `sum without (method) (x) * 2`                    | Use `by(...)`                                      | [#145308](https://github.com/elastic/elasticsearch/issues/145308)                                                                    |
  | 36  | Grouping by a label named `step`                                  | `sum by (step) (x)`                               | `step` is an output column of the `PROMQL` command | -                                                                                                                                    |
</table>

**Behaves differently**
<table>
  | #   | Construct                                                                                                                                      | Example            | Elasticsearch                     | Prometheus                                                                                  | Issue |
  |-----|------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|-----------------------------------|---------------------------------------------------------------------------------------------|-------|
  | 37  | `quantile`                                                                                                                                     | `quantile(0.9, x)` | Approximate, using t-digest       | Exact, with linear interpolation                                                            | -     |
  | 38  | `limitk`, `limit_ratio` <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> | `limitk(10, x)`    | A different, equally valid subset | A deterministic pseudo-random subset, with the `promql-experimental-functions` feature flag | -     |
</table>


## Functions

Rows follow [Functions](https://prometheus.io/docs/prometheus/latest/querying/functions/) in the Prometheus documentation and are sorted by function name.
Each [function reference entry](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/query-languages/promql/functions) lists further differences.
**Supported**
The functions in the [PromQL functions](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/query-languages/promql/functions) reference, such as `rate`, `increase`, `histogram_quantile`, `label_replace`, and the `<aggregation>_over_time` functions.
**Not supported yet**
<table>
  | #   | Construct                                                                                                                                                                                                                                    | Example                                                                                                                                | Workaround                                                                                                                                                                          | Issue                                                                                                                                                                                                   |
  |-----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
  | 39  | Functions listed under [Not supported yet](/elastic/docs-builder/docs/4268/reference/query-languages/promql/functions#promql-not-supported)                                                                                                  | `absent(x)`, `resets(x[1h])`, `info(x)`                                                                                                | -                                                                                                                                                                                   | [#164001](https://github.com/elastic/elasticsearch/issues/164001), [#164003](https://github.com/elastic/elasticsearch/issues/164003), [#164002](https://github.com/elastic/elasticsearch/issues/164002) |
  | 40  | Parameter that isn't a number literal                                                                                                                                                                                                        | `clamp_min(a, scalar(b))`, `histogram_quantile(scalar(a), b)`                                                                          | Use a number                                                                                                                                                                        | [#164225](https://github.com/elastic/elasticsearch/issues/164225)                                                                                                                                       |
  | 41  | `histogram_quantile` or `histogram_fraction` over `topk`, `bottomk`, `limitk`, or `limit_ratio` <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                       | `histogram_quantile(0.9, topk(5, a))`                                                                                                  | Aggregate with `by(...)` first: `histogram_quantile(0.9, topk(5, sum by (job, le) (a)))`                                                                                            | [#164226](https://github.com/elastic/elasticsearch/issues/164226)                                                                                                                                       |
  | 42  | `histogram_quantile` or `histogram_fraction` over `without(...)` <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                      | `histogram_quantile(0.9, sum without (instance) (rate(x[5m])))`                                                                        | Use `by(...)`                                                                                                                                                                       | [#157671](https://github.com/elastic/elasticsearch/issues/157671)                                                                                                                                       |
  | 43  | `histogram_stddev`, `histogram_stdvar` <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                          | `histogram_stddev(h)`                                                                                                                  | -                                                                                                                                                                                   | [#164152](https://github.com/elastic/elasticsearch/issues/164152)                                                                                                                                       |
  | 44  | `irate`, `delta` on native histograms <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                           | `irate(h[5m])`                                                                                                                         | -                                                                                                                                                                                   | [#152263](https://github.com/elastic/elasticsearch/issues/152263)                                                                                                                                       |
  | 45  | `label_replace` or `label_join` outside `by(...)`                                                                                                                                                                                            | `label_replace(x, "dst", "$1", "instance", "(.*):.*")`                                                                                 | <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> Use it inside `by(...)`: `sum by (dst) (label_replace(...))` | [#157672](https://github.com/elastic/elasticsearch/issues/157672)                                                                                                                                       |
  | 46  | `label_replace` or `label_join` over an aggregation <applies-to>Elastic Stack: Planned</applies-to>                                                                                                                                          | `label_replace(sum by (job) (x), ...)`                                                                                                 | -                                                                                                                                                                                   | [#157672](https://github.com/elastic/elasticsearch/issues/157672)                                                                                                                                       |
  | 47  | `label_replace` or `label_join` over anything other than a `by(...)` aggregation, or that overwrites a grouping label <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> | `label_replace(sum without (instance) (x), "dst", "$1", "job", "(.*)")`, `label_replace(sum by (job) (x), "job", "$1", "job", "(.*)")` | Aggregate with `by(...)` and write a new label: `label_replace(sum by (job) (x), "dst", "$1", "job", "(.*)")`                                                                       | [#157672](https://github.com/elastic/elasticsearch/issues/157672)                                                                                                                                       |
  | 48  | `label_replace` or `label_join` that writes a label named `step` <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                      | `label_replace(x, "step", ...)`                                                                                                        | `step` is an output column of the `PROMQL` command                                                                                                                                  | -                                                                                                                                                                                                       |
  | 49  | `predict_linear` with a horizon computed by a function <applies-to>Elastic Stack: Planned</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                                | `predict_linear(x[1h], time())`, `predict_linear(x[1h], scalar(y))`                                                                    | Use a number, a duration literal, or arithmetic on literals                                                                                                                         | [#164225](https://github.com/elastic/elasticsearch/issues/164225)                                                                                                                                       |
  | 50  | `rate` on native histograms <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to>                                                                     | `rate(h[5m])`                                                                                                                          | Use `increase`: `histogram_quantile(0.99, sum by (job) (increase(h[5m])))`                                                                                                          | [#152263](https://github.com/elastic/elasticsearch/issues/152263)                                                                                                                                       |
  | 51  | `sort` or `sort_desc` below the top level                                                                                                                                                                                                    | `sum(sort(x))`                                                                                                                         | Remove it. Sorting has no effect there                                                                                                                                              | [#164227](https://github.com/elastic/elasticsearch/issues/164227)                                                                                                                                       |
  | 52  | `step()`, `range()`, `start()`, `end()` (Prometheus: `promql-experimental-functions` feature flag)                                                                                                                                           | `time() - start()`                                                                                                                     | -                                                                                                                                                                                   | [#164228](https://github.com/elastic/elasticsearch/issues/164228)                                                                                                                                       |
</table>

**Behaves differently**
<table>
  | #   | Construct                                                                 | Example                               | Elasticsearch                                                                                    | Prometheus                                               | Issue |
  |-----|---------------------------------------------------------------------------|---------------------------------------|--------------------------------------------------------------------------------------------------|----------------------------------------------------------|-------|
  | 53  | `absent_over_time` with no data or over a gap                             | `absent_over_time(x{job="none"}[5m])` | No results                                                                                       | `1`, with the labels of the selector's equality matchers | -     |
  | 54  | `histogram_count`, `histogram_sum`, or `histogram_avg` on classic buckets | `histogram_count(rate(x_bucket[5m]))` | An error. They accept only native histograms                                                     | No results                                               | -     |
  | 55  | `quantile_over_time`                                                      | `quantile_over_time(0.9, x[5m])`      | Approximate, using t-digest                                                                      | Exact, with linear interpolation                         | -     |
  | 56  | `rate`, `increase`                                                        | `rate(x[5m])`                         | Computed over fixed time buckets, interpolated at bucket boundaries. Results can differ slightly | Extrapolated within each range window                    | -     |
</table>


## HTTP API

Sections follow [HTTP API](https://prometheus.io/docs/prometheus/latest/querying/api/) in the Prometheus documentation.
They apply only to the [Prometheus-compatible HTTP API](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/query-languages/promql/promql-http-api).

### Format overview

**Supported**
`GET` requests, and responses in the Prometheus JSON format.
**Behaves differently**
<table>
  | #   | Construct              | Example                                           | Elasticsearch                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Prometheus | Issue |
  |-----|------------------------|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|-------|
  | 57  | Form-encoded `POST`    | `Content-Type: application/x-www-form-urlencoded` | `406 Not Acceptable`.<applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> Accepted when [security](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/elasticsearch/configuration-reference/security-settings) is enabled, [`xpack.security.http.ssl.enabled`](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/elasticsearch/configuration-reference/security-settings) is `true`, and the request is authenticated. TLS must terminate at Elasticsearch. Otherwise, use `GET` | Accepted   | -     |
  | 58  | `warnings` and `infos` | `quantile(2, x)`                                  | Not returned. The only warning is `results truncated due to limit`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Returned   | -     |
</table>


### Expression queries

**Supported**
[Instant queries](/elastic/docs-builder/docs/4268/reference/query-languages/promql/promql-http-api#promql-http-api-query-instant) and [range queries](/elastic/docs-builder/docs/4268/reference/query-languages/promql/promql-http-api#promql-http-api-query-range).
**Not supported yet**
<table>
  | #   | Construct                                                                                                                                                        | Example                          | Workaround                                                              | Issue                                                             |
  |-----|------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------|-------------------------------------------------------------------------|-------------------------------------------------------------------|
  | 59  | Query parameters that the [PromQL HTTP API](https://www.elastic.co/elastic/docs-builder/docs/4268/reference/query-languages/promql/promql-http-api) doesn't list | `lookback_delta=1m`, `stats=all` | Configure clients to omit them. Elasticsearch returns `400 Bad Request` | [#149939](https://github.com/elastic/elasticsearch/issues/149939) |
</table>


### Querying metric metadata

**Supported**
<applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> The type and unit of each metric in [`/api/v1/metadata`](/elastic/docs-builder/docs/4268/reference/query-languages/promql/promql-http-api#promql-http-api-metadata-endpoint).
**Behaves differently**
<table>
  | #   | Construct                                                                                                                                                                                                                                                                                       | Example                | Elasticsearch | Prometheus               | Issue                                                             |
  |-----|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|---------------|--------------------------|-------------------------------------------------------------------|
  | 60  | `help` in [`/api/v1/metadata`](/elastic/docs-builder/docs/4268/reference/query-languages/promql/promql-http-api#promql-http-api-metadata-endpoint) <applies-to>Elastic Stack: Generally available since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Generally available</applies-to> | `GET /api/v1/metadata` | Empty         | The metric's `HELP` text | [#157230](https://github.com/elastic/elasticsearch/issues/157230) |
</table>


### Querying exemplars

**Not supported yet**
<table>
  | #   | Construct        | Example                       | Workaround                                                                      | Issue                                                             |
  |-----|------------------|-------------------------------|---------------------------------------------------------------------------------|-------------------------------------------------------------------|
  | 61  | Exemplar queries | `GET /api/v1/query_exemplars` | In Grafana, remove the links under **Data sources → Elasticsearch → Exemplars** | [#154786](https://github.com/elastic/elasticsearch/issues/154786) |
</table>