First off, it's recommended to always initialise all your potential label values to avoid this sort of issue.

This can be handled with the or operator:

sum by (type) (
     (increase(metric_hit[1d]) or metric_miss * 0)
  + 
     (increase(metric_miss[1d]) or metric_hit * 0)
)
Answer from brian-brazil on Stack Overflow
🌐
Google Groups
groups.google.com › g › prometheus-users › c › I7Vcd7nY41Q
Sum over range vector?
You can use sum_over_time(foo[5m]) to add up all the values in a metric over time. ... -- You received this message because you are subscribed to the Google Groups "Prometheus Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to prometheus-users+...
🌐
Prometheus
prometheus.io › docs › prometheus › latest › querying › functions
Query functions | Prometheus
The following example expression returns the per-second rate of HTTP requests looking up to 5 minutes back for the two most recent data points, per time series in the range vector: ... irate should only be used when graphing volatile, fast-moving counters. Use rate for alerts and slow-moving counters, as brief changes in the rate can reset the FOR clause and graphs consisting entirely of rare spikes are hard to read. Note that when combining irate() with an aggregation operator (e.g. sum()) or a function aggregating over time (any function ending in _over_time), always take an irate() first, then aggregate.
Discussions

monitoring - Prometheus Union of Ranged Vectors - Stack Overflow
I have two range vectors (# of hits and misses) that I want to aggregate by their types. Some of the types have hits, other misses, some with both. These are two independant metrics that I'm trying... More on stackoverflow.com
🌐 stackoverflow.com
Generating range vectors from return values in Prometheus queries - Stack Overflow
I have a metric varnish_main_client_req of type counter and I want to set up an alert that triggers if the rate of requests drops/raises by a certain amount in a given time (e.g. "Amount of re... More on stackoverflow.com
🌐 stackoverflow.com
prometheus - PROMQL: Calculate the sum_over_time of the product of two instant vectors - Stack Overflow
In Prometheus, you can do this to get a range vector: More on stackoverflow.com
🌐 stackoverflow.com
Prometheus : how do i sum by with 2 different metrics - Stack Overflow
I have 2 different metrics : metric_a with a field type metric_b with a field type (same one) I'm trying to summarise a and b, of the same type. If type exists only on metric_a and not on metric_... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Satyanash
satyanash.net › software › 2021 › 01 › 04 › understanding-prometheus-range-vectors.html
Understanding Prometheus Range Vectors - Satyajeet Kanetkar
January 4, 2021 - If a counter value drop below a previous recorded value, range vector functions like rate and increase will assume that the target restarted and add the entire value to the existing one it knows. This is also why we should always rate then sum ...
🌐
Prometheus
prometheus.io › docs › prometheus › latest › querying › basics
Querying basics | Prometheus
The offset modifier allows changing ... and range vectors in a query. For example, the following expression returns the value of http_requests_total 5 minutes in the past relative to the current query evaluation time: ... Note that the offset modifier always needs to follow the selector immediately, i.e. the following would be correct: sum(http_requ...
🌐
Robust Perception
robustperception.io › composing-range-vector-functions-in-promql
Composing range vector functions in PromQL – Robust Perception | Prometheus Monitoring Experts
December 5, 2016 - If you try and do max_over_tim... 3600) in Prometheus it won't work. How can you combine these functions? There are two general types of functions in PromQL that take timeseries as input, those that take a vector and return a vector (e.g. abs, ceil, hour, label_replace), and those that take a range vector and ...
Find elsewhere
🌐
FOSS TechNix
fosstechnix.com › home › vectors in prometheus with examples
Vectors in Prometheus with Examples
February 18, 2024 - Cannot: Cannot show trends over time; use range vectors for that. up: Indicates whether a target is currently reachable (1) or not (0). You can directly select a metric name to get an instant vector. Use label selectors to filter specific time series within the vector. PromQL functions like count(), min(), max(), etc., can be applied to instant vectors for aggregation. Examples: http_requests_total, up. prometheus_http_requests_total: Shows the total number of HTTP requests received by each endpoint at the moment.
🌐
SigNoz
signoz.io › guides › what is the difference between prometheus vectors - instant vs range explained
What is the Difference Between Prometheus Vectors - Instant vs Range Explained | SigNoz
October 14, 2024 - Think of range vectors as a video clip — they show you how metrics change over a defined period. ... Multiple Data Points: Captures a series of data points within a specified range of time. Trend Analysis: Useful for observing patterns and calculating rates. Aggregations: Enables operations like summing values over a time range.
🌐
SigNoz
signoz.io › guides › how to create range vectors in prometheus queries
How to Create Range Vectors in Prometheus Queries | SigNoz
November 20, 2024 - or: Returns values that match in either range vector. unless: Excludes values present in the second vector from the first vector. ... This query returns only data points where both http_requests_total and node_cpu_seconds_total are present within ...
🌐
Medium
giuscri.medium.com › about-sum-rate-in-prometheus-883e492ba542
About sum(rate…) in Prometheus - Giuseppe Crinò - Medium
January 17, 2023 - You can’t do the rate of a sum because you can’t use range selectors (i.e. [5m]) on the output of a function; as rate takes a range vector and one would write rate( sum(http_requests_total)[5m] ) the query is not allowed
🌐
Prometheus
prometheus.io › docs › prometheus › latest › querying › examples
Query examples | Prometheus
Note that an expression resulting in a range vector cannot be graphed directly, but viewed in the tabular ("Console") view of the expression browser.
🌐
Iximiuz
iximiuz.com › en › posts › prometheus-functions-agg-over-time
Prometheus Cheat Sheet - Moving Average, Max, Min, etc (Aggregation Over Time)
July 2, 2021 - Prometheus has a bunch of functions called <smth>_over_time(). They can be applied only to range vectors. It essentially makes them window aggregation functions.
🌐
DEV Community
dev.to › sre_panchanan › decoding-promql-a-deep-dive-into-prometheus-query-language-4h23
Decoding PromQL: A Deep Dive into Prometheus Query Language - DEV Community
November 12, 2024 - Here are examples illustrating the characteristics of the Range Vector data type in Prometheus: Sum of HTTP Request Rates over the Last 5 Minutes:
🌐
Coralogix
coralogix.com › home › promql tutorial: 5 tricks to become a prometheus god
PromQL Tutorial: 5 Tricks to Become a Prometheus God
June 3, 2025 - We’ll pass this vector into sum() aggregating along label app. Here’s the final query: sum( group(kube_pod_labels{label_app=~”redash-*”}) by (label_app, pod) * on (pod) group_right(label_app) label_replace sum by(pod_name)( rate(container_cpu_usage_seconds_total{namespace= “redash”[5m]) ), “pod”, “$1”, “pod_name”, “(.+)” )by label_app · Hopefully this PromQL tutorial has given you a sense for what the language can do. Prometheus takes its name from a Titan in Greek mythology, who stole fire from the gods and gave it to mortal man.
Top answer
1 of 2
17

This is the expected behavior when using a binary operator: both side must have a matching label set to be taken into account.

If you want to be able to aggregate both side and get the single one, you first must get the union of different metrics using the __name__ label:

 sum by(__name__,type)(metric_a{job=~"provision-dev"}) or on(__name__) sum by(__name__,type)(metric_b{job=~"provision-dev"})

You can cascade the aggregation operator:

sum by (type) (sum by (__name__,type)(metric_a{job=~"provision-dev"}) or on(__name__) sum by(__name__,type)(metric_b{job=~"provision-dev"}))

Finally, you can also compact everything into:

sum by (type) ({__name__=~"metric_a|metric_b",job=~"provision-dev"})
2 of 2
10

The following PromQL query should sum metric_a and metric_b by type:

(sum(metric_a) by (type) + sum(metric_b) by (type))
or
(sum(metric_a) by (type) unless sum(metric_b) by (type))
or
(sum(metric_b) by (type) unless sum(metric_a) by (type))

How it works:

  • The sum(metric_a) by (type) + sum(metric_b) by (type) sums time series with matching type label values on both sides of + according to matching rules
  • The sum(metric_a) by (type) unless sum(metric_b) by (type) returns sum(metric_a) by (type) results for type label values missing in sum(metric_b) by (type). See docs about unless operator.
  • The sum(metric_b) by (type) unless sum(metric_a) by (type) returns sum(metric_a) by (type) results for type label values missing in sum(metric_a) by (type).

Then results from these three queries are joined with or operator.

This query is equivalent to the query proposed by Michael: sum({__name__=~"metric_a|metric_b"}) by (type) .

P.S. This query can be simplified further when using MetricsQL:

sum(metric_a, metric_b) by (type)

This query works, since sum() function in MetricsQL accepts and sums arbitrary number of arguments.

Top answer
1 of 10
42

Summary from

  • Understanding Prometheus Range Vectors
  • The Anatomy of a PromQL Query

  • What’s a Vector?
    • Since Prometheus is a timeseries database, all data is in the context of some timestamp. The series that maps a timestamp to recorded data is called a timeseries
    • a set of related timeseries is called a vector
    • Ex.
      • http_requests_total is a vector representing the total number of http requests received by a service
      • http_requests_total{code="200"} http_requests_total refers to the entire set of timeseries that are named that. And by appending a {code="200"}, we’re selecting a subset.
  • Types of Vectors
    • Instant vector - a set of timeseries where every timestamp maps to a single data point at that “instant”
      • Imagine evaluating the expression http_requests_total at a given timestamp. http_requests_total is an instant vector selector that selects the latest sample for any time series with the metric name http_requests_total. More specifically, "latest" means "at most 5 minutes old and not stale", relative to the evaluation timestamp. So this selector will only yield a result for series that have a sample at most 5 minutes prior to the evaluation timestamp, and where the last sample before the evaluation timestamp is not a stale marker (an explicit way of marking a series as terminating at a certain time in the Prometheus TSDB).
    • Range vector - a set of timeseries where every timestamp maps to a “range” of data points, recorded some duration into the past.
      • Range vector is mostly used for graphs, where you want to show a PromQL expression over a given time range. A range query works exactly like many completely independent instant queries that are evaluated at subsequent time steps over a given range of time. Of course, this is highly optimized under the hood and Prometheus doesn't actually run many independent instant queries in this case.
  • Differences
    • Instant vectors can be charted; Range vectors cannot. This is because charting something involves displaying a data point on the y-axis for every timestamp on the x-axis. Instant vectors have a single value for every timestamp, while range vectors have many of them. For the purpose of charting a metric, it is undefined1 how to show multiple data points for a single timestamp in a timeseries.
    • Instant vectors can be compared and have arithmetic performed on them; Range vectors cannot. This is also due to the way comparison and arithmetic operators are defined. For every timestamp, if we have multiple values, we don’t know how to add1 or compare them to another timeseries of a similar nature.
    • Range Vectors for counters. We take the instant vector and append our duration [15m]. This part is called the range selector and it transforms the instant vector into a range vector. We then use a function like increase which effectively subtracts the data point at the start of the range from the one at the end. increase(http_requests_total{code="200",handler="/api/v1/query"}[15m]) represent it is the increase in the total number of requests over the past fifteen minutes
2 of 10
24

VictoriaMetrics author here. This is Prometheus-like monitoring system, which supports PromQL-like query language - MetricsQL.

The instant vector and range vector are indeed confusing terms in Prometheus. That's why these terms are avoided in VictoriaMetrics docs. Prometheus query language - PromQL - provides various functions, which can be divided into two groups:

  • Functions, which accept only instant vector. Such functions can be split into the following subgroups:
    • transform functions, which apply various transformations individually per each input time series. For example, abs()
    • label manipulation functions, which modify labels and metric names for the input time series. For example, label_replace()
    • aggregate functions, which aggregate multiple input time series into specified groups of output time series. For example, sum(). Fun fact is that aggregate functions are named aggregation operators in Prometheus - see these docs.
  • Functions, which accept only range vector. VictoriaMetrics names such functions as rollup functions, since they calculate the result based on input time series samples over the given lookbehind window specified in square brackets (aka sliding window). For example, rate(http_requests_total[5m]) calculates the average per-second increase rate for http_requests_total time series over the last 5 minutes.

From user's perspective the only difference between instant vector and range vector is that range vector is constructed from the instant vector by adding a lookbehind window in square brackets. For example, http_requests_total is an instant vector, while http_requests_total[5m] is a range vector. I'd say that the range vector syntax is just a syntactic sugar for rollup functions in PromQL. E.g. rate(m[d]) could be written as rate(m, d), e.g. the lookbehind window d could be passed as a separate argument to rollup functions.

Top answer
1 of 2
1

Is there any way to perform an instant vector operation on a range vector?

No. Prometheus doesn't allow anything like this.

But you can apply range selector over something other than vector selector using subquery syntax. So in your example it would be something like.

avg(avg_over_time((count_containers > 0)[1h:15s]))

Notice that in this case you must place : in the range selector to indicate usage of subquery.

And for this example I used resolution 15s, to indicate that result of the query should be calculated for each 15 seconds window. But you might want to adjust this to your needs, depending on needed precision, scrape interval, etc. Also, resolution can be omitted (while preserving :, like [1h:]): in that case value of evaluation_interval will be used.


we want to count the fraction of the time where we have at least one, we might try to do:

Your attempt of the query, even if it were supported, would not produced what you wanted. Rather it would calculate average number of containers when number of containers was positive.

To calculate percentage of the time when number of containers was positive use following

avg(avg_over_time( (count_containers > bool 0)[1h:15s] ))

Expression count_containers > bool 0 will return 1 if number of containers is positive, and 0 otherwise.

2 of 2
1

If you want calculating the share of time when count_containers was positive during the last hour, it is better to use the following PromQL query:

sum(sum_over_time((count_containers >bool 0)[1h:15s]))
  /
sum(count_over_time(count_containers[1h:15s]))

This query uses the following PromQL features:

  • subquery
  • > operator with bool modifier
  • sum_over_time and count_over_time rollup functions
  • sum aggregate function
  • / binary operator.

Note that the avg(avg_over_time(...)) query may return unexpected results, since average of averages may not equal to the average.

P.S. the query above assumes that the interval between raw samples of a single time series equals to 15 seconds - see 15s in square brackets after the colon in the query above. This interval is also known as scrape_interval in Prometheus ecosystem. If your data has different scrape interval, then the value in square brackets should be adjusted in the query above. Otherwise query results will be incorrect.

P.P.S. The query can be simplified to the following one with share_gt_over_time function in MetricsQL - PromQL-like query language I work on:

share_gt_over_time(count_containers[1h], 0)
🌐
Last9
last9.io › blog › how-sum_over_time-works-in-prometheus
sum_over_time in Prometheus: Syntax and Pitfalls | Last9
July 25, 2025 - This function works with range vectors, not instant vectors, so you’ll always pair it with a time selector like [5m] or [1h]. The result is a single aggregated value per time series that represents the sum of all raw samples in that window.