You can use the argument list of group_left to include extra labels from the right operand (parentheses and indents for clarity):

(
  max(consul_health_service_status{status="critical"}) 
  by (service_name,status,node) == 1
)
   + on(service_name,node) group_left(env)
(
   0 * consul_service_tags
)

The important part here is the operation + on(service_name,node) group_left(env):

  • the + is "abused" as a join operator (fine since 0 * consul_service_tags always has the value 0)
  • group_left(env) is the modifier that includes the extra label env from the right (consul_service_tags)
Answer from user2361830 on Stack Overflow
🌐
GitHub
github.com › prometheus › prometheus › issues › 15146
simpler syntax for joins on labels with different names · Issue #15146 · prometheus/prometheus
October 10, 2024 - Background When doing joins, I usually encounter cases where I want to join through a label that has different names on each side. For example, suppose I have: A container_fs_reads_total metric wit...
Author: prometheus
Discussions

monitoring - How can I 'join' two metrics in a Prometheus query? - Stack Overflow
It doesn't look to me like any operations or functions give me the ability to group or join like this. As far as I can see, the tags would already need to be labels on the consul_health_service_status metric. ... There is a good article with visual description of joining vectors in a Prometheus. More on stackoverflow.com
🌐 stackoverflow.com
Promql join on different label names - Stack Overflow
Is it possible implement in promql a.foo = b.bar join? ... I've implemented by using label_replace for renaming label. More on stackoverflow.com
🌐 stackoverflow.com
Prometheus - join series based on the key part of a label - DevOps Stack Exchange
In 1.16 k8s deprecated the label kubernetes.io/role: worker I had previously been using as a filter to target graphs to specific node role using this in my grafana variables declaration label_values( More on devops.stackexchange.com
🌐 devops.stackexchange.com
February 28, 2020
prometheus - PromQL join with identical label value but different label name - Stack Overflow
I am struggling with the label_replace function since I am pretty sure it's what I need. The answer here also suggests it: Promql join on different label names More on stackoverflow.com
🌐 stackoverflow.com
🌐
Yannick Pereira-Reis
ypereirareis.github.io › blog › 2020 › 02 › 21 › how-to-join-prometheus-metrics-by-label-with-promql
How to join Prometheus metrics by label with PromQL – Yannick Pereira-Reis
How to query prometheus to have sum of “disk bytes read” by instance/node/server name ? The result we want is something like that : node2 => 22082332072448 node4 => 8439202548224 node5 => 28203612148224 node6 => 56887513977344 node3 => 30887053824 node1 => 36352176166912 · sum(node_disk_bytes_read * on(instance) group_left(node_name) node_meta{}) by (node_name) on(instance) => this is how to JOIN on label instance.
🌐
Google Groups
groups.google.com › g › prometheus-users › c › qlHK7r1hQVs
Joining two metrics in promtheus and having all labels from both
March 6, 2023 - To view this discussion on the ... member email addresses permission to view the original message ... But yes, you'll have to treat it as a many-to-one in order to pick up the extra labels....
Top answer
1 of 3
76

You can use the argument list of group_left to include extra labels from the right operand (parentheses and indents for clarity):

(
  max(consul_health_service_status{status="critical"}) 
  by (service_name,status,node) == 1
)
   + on(service_name,node) group_left(env)
(
   0 * consul_service_tags
)

The important part here is the operation + on(service_name,node) group_left(env):

  • the + is "abused" as a join operator (fine since 0 * consul_service_tags always has the value 0)
  • group_left(env) is the modifier that includes the extra label env from the right (consul_service_tags)
2 of 3
15

It is a good practice in Prometheus ecosystem to expose additional labels, which can be joined to multiple metrics, via a separate info-like metric as explained in this article. For example, consul_service_tags metric exposes a set of tags, which can be joined to metrics via (service_name, node) labels.

The join is usually performed via on() and group_left() modifiers applied to * operation. The * doesn't modify values for time series on the left side because info-like metrics usually have constant 1 values. The on() modifier is used for limiting the labels used for finding matching time series on the left and the right side of *. The group_left() modifier is used for adding additional labels from time series on the right side of *. See these docs for details.

For example, the following PromQL query adds env label from consul_service_tags metric to consul_health_service_status metric with the same set of (service_name, node) labels:

consul_health_service_status
  * on(service_name, node) group_left(env)
consul_service_tags

Additional label filters can be added to consul_health_service_status if needed. For example, the following query returns only time series with status="critical" label:

consul_health_service_status{status="critical"}
  * on(service_name, node) group_left(env)
consul_service_tags
🌐
Iximiuz
iximiuz.com › en › posts › prometheus-vector-matching
Prometheus Cheat Sheet - How to Join Multiple Metrics (Vector Matching)
November 30, 2021 - multiple matches for labels: many-to-one matching must be explicit (group_left/group_right) Unless logical binary operator and|unless|or is used, Prometheus always considers at least one side of the binary operation as having the cardinality of "one".
🌐
Grafana
grafana.com › blog › 2021 › 08 › 04 › how-to-use-promql-joins-for-more-effective-queries-of-prometheus-metrics-at-scale
How to use PromQL joins for more effective queries of Prometheus metrics at scale | Grafana Labs
August 5, 2021 - For some example scripts that can ... the ability to join two metrics together: You can append a label set from one metric and append it to another at query time....
Find elsewhere
🌐
Super User
superuser.com › questions › 1768794 › prometheus-join-on-metric-value-rather-than-label
Prometheus join on metric value, rather than label? - Super User
February 15, 2023 - For background, the ipAddressAddr label contains the (redacted) IP of a second interface on the device, so sadly it's not as simple as using the instance address. ... You can do such a join using == and group_left.
🌐
Google Groups
groups.google.com › g › prometheus-users › c › LgGTcR-jQvs
Join by field (outer join) with different names
October 12, 2020 - Joining the two queries results would permit to get some more informations into the same table. ... Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message ... label_replace(lldpLocPortDesc, "ifIndex", "$1", "lldpLocPortNum", "(.+)") If that works, then you should be able to build a query on top of this which uses (instance, ifIndex) as the join labels.
🌐
OneUptime
oneuptime.com › home › blog › how to join two metrics in prometheus query
How to Join Two Metrics in Prometheus Query
December 17, 2025 - Joining metrics in Prometheus requires understanding vector matching and label cardinality. Use on() to specify which labels to match, and group_left() or group_right() when cardinalities differ.
🌐
Robust Perception
robustperception.io › left-joins-in-promql
Left joins in PromQL – Robust Perception | Prometheus Monitoring Experts
December 30, 2019 - PromQL by default effectively does an inner join and requires that labels (except the metric name) on both sides of the expression to be exactly the same and match one-to-one. There's no way in PromQL to increase your cardinality (other than absent(), which can only go from 0 to 1).
🌐
Stack Overflow
stackoverflow.com › questions › 79231136 › promql-join-with-identical-label-value-but-different-label-name
prometheus - PromQL join with identical label value but different label name - Stack Overflow
( aws_certificatemanager_days_to_expiry_average + on (name) group_left(tag_Name) aws_certificatemanager_info ) Is that the labels for the AWS ARN where I want to join are different named in the metrics.
🌐
Reddit
reddit.com › r/prometheusmonitoring › combine values form the same metric, but different label values.
r/PrometheusMonitoring on Reddit: Combine values form the same metric, but different label values.
September 7, 2021 - Reason I want to join all the values is because I want to get the "true" value for probe_success metric. There's actually more data points for the first series than the second one. So the first series is "weighted" more. I tried label_replace function, but since the values are different it won't work.
🌐
Atatus
atatus.com › blog › how-to-join-two-metrics-in-prometheus
How to Join two metrics in Prometheus?
August 12, 2025 - How to Avoid: Limit your join operations to only essential labels by using the on() and ignoring() modifiers. Metric joining enables combining metrics for deeper insights using PromQL. Prometheus supports four metric types: Counter, Gauge, Histogram, and Summary. Labels add context to metrics, helping differentiate data based on specific attributes.
Top answer
1 of 2
2

The main roadblock you are probably hitting is the fact that the in both metrics you have the status label which is different AND the one you want to replicate. Prometheus won't be able resolve it while the label names collide.

The first thing you want to do is generate a new timeseries with a different label name for the second status. You can do this by using label_replace. For example:

label_replace(metric2{...}, "metric2_status", "$1", "status", "(.*)")

This will keep the status label but will also add a metric2_status with the value of the status label.

Now you can proceed to use on() and group_left(). These need to be used with an arithmetic or group function. If you are using this to add more labels to metric1, remember to use an arithmetic that will not alter the metric value.

For example - assuming metric2 has always a value of 1 - this is what you could use:

metric1{label_1="a", ...} * 
    on (label_a, label_b) 
    group_left(metric2_status)
label_replace(metric2{...}, "metric2_status", "$1", "status", "(.*)")

the resulting metric should have metric1's labels plus the metric2_status label.

2 of 2
0

When using group modifiers such as

ignoring()
on()
group_left()
group_right()

the label(s) used in on() modifier must be unique at least in one vector.

Consider metric1, metric2 vectors and common label_a=... label used in on(). These cases may occur

If metric1 has unique label_a=... and metric2 has unique label_a=... we have one-to-one match.

If metric1 has duplicate label_a=... and metric2 has unique label_a=... we have many-to-one match.

If metric1 has unique label_a=... and metric2 has duplicate label_a=... we have one-to-many match.

If metric1 has duplicate label_a=... and metric2 has duplicate label_a=... we have many-to-many match and vectors are not joinable.

Additionally the result vector must have unique set of label keys. That's why we are renaming the label in the right-hand side vector and joining it as a label with different name.

Working query is

( metric1{...} == 1 ) *
    on(label_a)
    group_left(metric2_status)
label_replace((metric2{...} == 1), "metric2_status", "$1", "status", "(.*)")

( metric1{...} == 1 )

Filter metric1 so that the left-hand side of the query contains only data with unique label_a=....

on(label_a)

join two metrics on label_a=....

group_left(metric2_status)

add metric2_status label from right-hand metric2.

label_replace((metric2{...} == 1), "metric2_status", "$1", "status", "(.*)")

create new label metric2_status in metrics2 from the status label.

🌐
about:farcaller
farcaller.net › posts › this is how you merge labels from several prometheus metrics
This is how you merge labels from several prometheus metrics | about:farcaller
May 31, 2024 - we take the values of node_hwmon_temp_celsius (1), and group it (4) with the additional label of label from node_hwmon_sensor_label (5) using the job, chip, and sensor (3) as the labels to group on. As you can only do vector matching on bin-ops, we also divide (2) the value of temp over the ...
🌐
SigNoz
signoz.io › guides › how can i 'join' two metrics in a prometheus query? - joining metrics in promql
How can I 'join' two metrics in a Prometheus query? - Joining Metrics in PromQL | SigNoz
July 24, 2024 - This approach allows for a holistic view of your system's health and performance. Vector matching is the primary method for joining metrics in PromQL. It allows you to combine time series based on their label sets.
🌐
Better Stack
betterstack.com › community › questions › how-to-join-two-metric-in-one-prometheus-query
How Can I 'Join' Two Metrics in a Prometheus Query? | Better Stack Community
Joining two metrics in Prometheus is commonly achieved through the use of the * operator or the group function, allowing you to perform operations between metrics based on their labels.