The goal is to make it easier to write PromQL queries in Kibana by making all parameters optional and to make them automatically adapt to the selected time range.
Auto-step
Currently, range queries require setting the step parameter. However, we don't offer ways to make the step dynamic. This makes it hard to use in Kibana as the step doesn't adapt to the selected time range. While a 10s step makes sense when looking at the data from the last 15 minutes, it needs to be larger when selecting the last 7 days.
We already have similar functionality for the BUCKET command, which allows to specify a target number of buckets and the time range. Based on that, it automatically determines the appropriate bucket size.
Let's make something similar available in PromQL. For example, we could introduce a bucket parameter with a reasonable default value (e.g. 100). It will require the currently optional start/end parameters to be set.
Example query:
PROMQL start="2026-02-17T08:00:00Z" end="2026-02-17T09:00:00Z" sum(rate(http_requests_total[5m])
PR:
Infer start/end
The previous section mentions that the start and end parameters are required to benefit from auto-bucketing. This isn't a great user experience in Kibana as the queries usually don't include an explicit date filter. That's because Kibana automatically adds a Query DSL filter to the request, without it bing part of the ES|QL query itself.
There are placeholders that allow using the selected time range for the start/end parameters:
PROMQL start=?_tstart end=?_tend sum(rate(http_requests_total[5m])
However, setting this now becomes required if you want to benefit from auto-bucketing. Is there a way where users don't need to explicitly add them to the query? There is if we infer the start/end from the Query DSL filter Kibana is adding.
Example ES|QL request Kibana is executing ...
{
"params": {
"query": "TS metrics-*.otel-default| STATS avg(container.cpu.time)",
"time_zone": "Europe/Berlin",
"locale": "en",
"include_execution_metadata": true,
"filter": {
"bool": {
"must": [],
"filter": [
{
"range": {
"@timestamp": {
"format": "strict_date_optional_time",
"gte": "2026-02-17T07:21:29.148Z",
"lte": "2026-02-17T07:36:29.148Z"
}
}
}
],
"should": [],
"must_not": []
}
},
"dropNullColumns": true
}
}
We can inspect the range filter on the @timestamp field and infer the start/end from that.
With that, the query shrinks to this:
PROMQL sum(rate(http_requests_total[5m])
This query has a target bucket count of 100 and is responsive to the date selector.
PR:
Auto-determine range selector window
There's still a remaining issue: the range selector window is set to a fixed size ([5m] in the example) while it should also be responsive to the bucket size.
Grafana deals with that by exposing a $__rate_interval placeholder. The placeholder can be used in queries like this: sum(rate(http_requests_total[$__rate_interval]). This works well and is probably the only option for regular PromQL.
VictoriaMetrics solves this a little more elegantly by extending the language to not require a range selector here: sum(rate(http_requests_total). This will automatically determine the window by using max of the step and the scrape_interval plus a little buffer to account for jitter (metrics not always arriving a the exact same rate). It determines the scrape_interval by looking at the raw data during execution.
Automatically detecting the scrape interval based on the raw data at execution time is pretty neat, but that would be hard to incorporate into the way we do global planning and distributed (shard/segment-level) execution. We could have a similar but simplified logic where the scrape_interval is a parameter of the PROMQL command (with a reasonable default value).
We can then express the query as
PROMQL sum(rate(http_requests_total)
PR:
In summary
- The simple query above is now fully responsive to the date picker in Kibana, and adjusts the size of the buckets as well as the range selector window dynamically. Aside from the query itself, no parameters are required.
- The range window makes sure there's always at least one value to evaluate by taking into account the
scrape_interval parameter (or its default value if not specified explicitly).
- Users don't need to explicitly specify the start/end parameters as they're inferred from the Query DSL filter Kibana adds.
- The number of target buckets defaults to a reasonable value like 100 based on the explicit or inferred start/end range, and can be customized if more or less granularity is needed.
The goal is to make it easier to write PromQL queries in Kibana by making all parameters optional and to make them automatically adapt to the selected time range.
Auto-step
Currently, range queries require setting the
stepparameter. However, we don't offer ways to make the step dynamic. This makes it hard to use in Kibana as the step doesn't adapt to the selected time range. While a 10s step makes sense when looking at the data from the last 15 minutes, it needs to be larger when selecting the last 7 days.We already have similar functionality for the
BUCKETcommand, which allows to specify a target number of buckets and the time range. Based on that, it automatically determines the appropriate bucket size.Let's make something similar available in PromQL. For example, we could introduce a
bucketparameter with a reasonable default value (e.g. 100). It will require the currently optional start/end parameters to be set.Example query:
PR:
Infer start/end
The previous section mentions that the start and end parameters are required to benefit from auto-bucketing. This isn't a great user experience in Kibana as the queries usually don't include an explicit date filter. That's because Kibana automatically adds a Query DSL filter to the request, without it bing part of the ES|QL query itself.
There are placeholders that allow using the selected time range for the start/end parameters:
However, setting this now becomes required if you want to benefit from auto-bucketing. Is there a way where users don't need to explicitly add them to the query? There is if we infer the start/end from the Query DSL filter Kibana is adding.
Example ES|QL request Kibana is executing ...
{ "params": { "query": "TS metrics-*.otel-default| STATS avg(container.cpu.time)", "time_zone": "Europe/Berlin", "locale": "en", "include_execution_metadata": true, "filter": { "bool": { "must": [], "filter": [ { "range": { "@timestamp": { "format": "strict_date_optional_time", "gte": "2026-02-17T07:21:29.148Z", "lte": "2026-02-17T07:36:29.148Z" } } } ], "should": [], "must_not": [] } }, "dropNullColumns": true } }We can inspect the range filter on the
@timestampfield and infer the start/end from that.With that, the query shrinks to this:
This query has a target bucket count of 100 and is responsive to the date selector.
PR:
Auto-determine range selector window
There's still a remaining issue: the range selector window is set to a fixed size (
[5m]in the example) while it should also be responsive to the bucket size.Grafana deals with that by exposing a $__rate_interval placeholder. The placeholder can be used in queries like this:
sum(rate(http_requests_total[$__rate_interval]). This works well and is probably the only option for regular PromQL.VictoriaMetrics solves this a little more elegantly by extending the language to not require a range selector here:
sum(rate(http_requests_total). This will automatically determine the window by using max of the step and the scrape_interval plus a little buffer to account for jitter (metrics not always arriving a the exact same rate). It determines the scrape_interval by looking at the raw data during execution.Automatically detecting the scrape interval based on the raw data at execution time is pretty neat, but that would be hard to incorporate into the way we do global planning and distributed (shard/segment-level) execution. We could have a similar but simplified logic where the
scrape_intervalis a parameter of the PROMQL command (with a reasonable default value).We can then express the query as
PR:
In summary
scrape_intervalparameter (or its default value if not specified explicitly).