Understand cardinality and active series

Cardinality is the number of distinct values an attribute can have. In observability, it determines how many unique series and streams your labels create, and that number can significantly impact your cost and performance.

What you’re actually billed for

A common misconception is that metrics billing is per metric name. It isn’t. A time series is a metric name plus one unique combination of label key-value pairs, and each series that receives data within the last 20 minutes counts as an active series. Grafana Cloud bills metrics on the 95th percentile of your active series count over the billing period, so one metric name with many label combinations can cost far more than dozens of well labeled metrics.

Logs work the same way structurally, though cost attribution is different.

Anatomy of a time series and a log stream, showing that each unique combination of label values creates one series or stream

Labels multiply series

Labels don’t add series, they multiply them. A status label with 3 values combined with an action label with 5 values produces 15 unique series from what looks like one metric. Add an endpoint label with 3 values and you’re at 45. Every label you add multiplies the count by that label’s number of values.

Two rows showing label value counts multiplying. 3 status values times 5 action values equals 15 series, and adding a 3-value endpoint label grows the total to 45 series

Cardinality affects cost and performance

High cardinality affects both your bill and query performance, but metrics and logs are billed differently.

  • Metrics cost. Grafana Cloud bills metrics on active series, so every unique label combination is a billing unit, whether or not anyone queries it.
  • Logs cost. Grafana Cloud bills logs on GB processed and ingested, not per stream. High stream cardinality doesn’t add a direct per-stream charge, but it can inflate query costs because larger indexes and more chunks mean bigger scans.
  • Performance. For logs, many streams mean a large index and many small chunks, which slows queries down. Loki is designed for low-cardinality labels and limits index labels to 15 by default.

High-cardinality attributes to watch for include user IDs, request or trace IDs, IP addresses, Kubernetes pod names, and timestamps. Any of these used as a label value creates a new series or stream for every unique value.

You now have the core model: labels multiply into series and streams, and you pay for every unique combination. Next, you’ll look at your own stack’s cardinality.


More to explore (optional)

At this point in your journey, you can explore the following topics:


page 3 of 9