Computing Ratios
Some of the most useful metrics are not raw counters — they are ratios between two metrics. The classic example is error rate: what fraction of requests are failing? Computing it as a percentage means dividing the summed rate of 5xx responses by the summed rate of all responses, then multiplying by 100.
Why rate() on both sides? You cannot divide raw counters because they grow indefinitely and at different rates depending on when each pod started. Dividing rates gives you a dimensionless ratio that is stable and meaningful.
The 5.. regex matches any status code starting with 5 (500, 502, 503, etc.).
Label Matching in Binary Operations
When you divide two vectors, PromQL matches time series by their label sets. If the left side has {job="api-server", method="GET"} and the right side has {job="api-server"}, they do not match — the label sets differ.
Use on() or ignoring() to control matching: aggregating the numerator and denominator both by (job) before dividing them sidesteps mismatched label sets entirely — the division works cleanly once both sides share the same reduced label set.
The absent() Function
absent(metric_name) returns 1 if the metric has no data (the series does not exist), and returns nothing if the metric exists. This is used in alerting rules to detect when a service has stopped reporting entirely — a "missing data" alert, for example wrapping up{job="api-server"} to catch the API server going dark.