Demystifying PromQL: How Nested Functional Queries Work in Prometheus
This article explores the structure and evaluation of PromQL queries, covering its nested functional language nature, expression types, time handling with instant and range queries, and practical examples using the PromLens visualizer, helping readers grasp how Prometheus processes and types queries.
1. PromQL is a nested functional language
Unlike SQL or other command‑style query languages, PromQL is a nested functional language where data is described as a hierarchy of expressions, each producing an intermediate value without side effects. The outermost expression yields the final result shown in tables, graphs, or similar use cases.
# Root of the query, final result, approximates a quantile.
histogram_quantile(
# 1st argument to histogram_quantile(), the target quantile.
0.9,
# 2nd argument to histogram_quantile(), an aggregated histogram.
sum by(le, method, path) (
# Argument to sum(), the per-second increase of a histogram over 5m.
rate(
# Argument to rate(), the raw histogram series over the last 5m.
demo_api_request_duration_seconds_bucket{job="demo"}[5m]
)
)
)PromQL expressions can be evaluated at any nested part (e.g., the rate(...) sub‑expression) as independent queries. In the example, each comment line corresponds to an expression.
When analyzing the same query in the PromLens visualizer, the nested expression tree becomes especially clear:
In PromLens you can click each tree node to evaluate its sub‑expression and see the data processed at that part of the tree.
2. Input expressions may not be what you expect
Prometheus has two kinds of “type” concepts:
Metric types reported by scrape targets: counter, gauge, histogram, summary, or untyped.
PromQL expression types: string, scalar, instant vector, or range vector.
PromQL ignores metric types and only cares about expression types. Every expression has a type, and functions or operators require specific types. For example, rate() expects a range vector and returns an instant vector.
Possible PromQL expression types are:
String: e.g., "I am a string!". Used only as arguments to some functions.
Scalar: a single number without a unit, e.g., 1.234. Used in functions like histogram_quantile(0.9, …) or arithmetic.
Instant vector: a set of time‑series each with a single sample at the same timestamp. Can come directly from a selector or from a function.
Range vector: a set of time‑series each containing a range of samples. Produced by range selectors (e.g., metric[5m] ) or sub‑queries.
node_cpu_seconds_total{cpu="0", mode="idle"} → 19165078.75 @ timestamp_1
node_cpu_seconds_total{cpu="0", mode="system"} → 381598.72 @ timestamp_1
node_cpu_seconds_total{cpu="0", mode="user"} → 23211630.97 @ timestamp_1Metric type matters for certain functions: histogram_quantile() works only with histogram metrics, rate() with counters, deriv() with gauges. PromQL does not enforce metric‑type compatibility, so mismatched inputs may produce meaningless results.
3. How time enters: instant vs. range queries
PromQL references time only via relative ranges (e.g., [5m]). Absolute time ranges and timestamps are supplied to the Prometheus HTTP API. There are two query types: instant queries and range queries.
3.1 Instant queries
Instant queries return results for a single evaluation timestamp, useful for table‑like views.
Parameters:
PromQL expression.
Evaluation timestamp.
The expression is evaluated at the given timestamp; selectors can look back over a window but cannot select future data. Instant queries can return any valid expression type (string, scalar, instant vector, or range vector).
Example: evaluating http_requests_total at a specific timestamp returns the latest sample within the last five minutes.
Note that the output timestamps are set to the evaluation timestamp.
If no recent sample exists within the look‑back window, the query returns an empty result.
3.2 Range queries
Range queries are used for graphs, evaluating the same expression repeatedly over a time interval.
Parameters:
PromQL expression.
Start time.
End time.
Step (resolution).
Each step is evaluated like an instant query, and the results are concatenated into a range vector. The query may start from an instant vector or scalar, but the final result is always a range vector.
Example visualisation of the earlier expression as a range query:
Conclusion
Hopefully this blog post gives you a better understanding of PromQL query structure, the (lack of) type checking, and how queries are parsed and evaluated.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
