Skip to main content

Differences between AxQL and PromQL

While AxQL and PromQL are both designed for querying metrics data, they differ in fundamental ways that impact how queries are written and interpreted. This section outlines the key differences to help you adapt PromQL workflows when migrating to Axiom.

Richer type system

Prometheus treats all label values as strings, which often leads users to rely heavily on regular expressions for filtering. AxQL, by contrast, supports a broader and more expressive type system, including native types like numbers, booleans, and timestamps. This means you can write cleaner, type-aware queries and avoid the pitfalls of string-only comparisons. For OpenTelemetry (OTel) data, this difference means that AxQL preserves source types, enabling more accurate and efficient filtering and aggregation.

Labels versus fields

PromQL is optimized for a sparse label space and performs poorly with high-cardinality label sets. This design limits how many dimensions can be encoded as labels. AxQL doesn’t impose the same restrictions. It encourages richer, high-cardinality data ingestion, allowing you to store and query more attributes per event without performance degradation. Additionally, PromQL users often use enrichment queries simulate dimensional joins and join label values from one series into another. AxQL doesn’t currently support this pattern because it diverges from OpenTelemetry semantics, which emphasize event-based modeling over metric enrichment.

Histogram behavior

Histogram support differs significantly. In PromQL, histogram queries typically yield one time series per bucket or a single quantile series depending on the function. AxQL allows histogram operations that can output multiple series in a single query, providing greater flexibility for analyzing distributions or rendering percentile summaries directly.

Regular expression syntax

In PromQL, regular expressions are written as string literals. This requires escaping special characters using double quotes and backslashes, which can be error-prone. AxQL treats regular expressions as a first-class type. They’re written directly without string escaping, making them easier to use and less ambiguous.
Regex is a native type in AxQL. Denote regex using slash (/) instead of quotation marks (' or ").In regex, escape slash (/), but don’t escape quotation marks (' or ").

Examples

Average over time

avg_over_time(
   (
      max(
          axiomdb_transport_ingest_pressure\{
             time_window = "1m",
              service =~ "axiomdb-[a-f]"
          \}
       ) <bool 0.4
   )[7d:]
)

Multiply each value by 100

http_request_duration_seconds_count{} * 100

Calculate average error rate

Calculate the average error rate per 5-minute windows on a set of HTTP endpoints.
sum(rate(http_request_duration_count{           container=~"ingest|api|login", path=~".*(ingest|(?:v1/(traces|logs))).*", code!~"[1234].."}[5m]))
/
sum(rate(http_request_duration_count{container=~"ingest|api|login", path=~".*(ingest|(?:v1/(traces|logs))).*"}[5m]))

Calculate CPU saturation

Calculate CPU saturation (actual over requested) of each service.
max(
  label_replace(
  (sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=~"(axiom|cloud).*",pod=~"ingest-.*"}) by (pod)
    /
    sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=~"(axiom|cloud).*", pod=~"ingest-.*", resource="cpu"}) by (pod)),
  "service", "$1", "pod", "(.+)-.+-.+")
) by (service)

Calculate rate

Calculate rate of HTTP requests by method, path and http response code.
sum by (method, path, code) (
      rate(
          http_requests_total{
              path=~".*(ingest|(?:v1/(traces|logs))).*",
              code=~"[123].."
          }[5m]
      )
  )
I