Metric Cardinality
The number of unique label-value combinations on a metric, which multiplies into the number of time series stored and is the primary driver of monitoring cost and failure.
Each unique combination of label values is a separate time series, and cost scales with the product of the label cardinalities.
The arithmetic that surprises people: a metric with 10 endpoints × 5 status codes × 3 regions is 150
series — fine. Add user_id with a million values and it becomes 150 million. This is the most common
way a monitoring system is taken down, and it is usually done in a single well-intentioned commit.
Unbounded labels to never use: user ID, request ID, session ID, trace ID, full URL with parameters, email address, timestamp, error message text.
Bounded labels that are safe: endpoint (as a route pattern, not a URL), status code, region, service version, tenant tier.
The rule that makes the decision easy: high-cardinality data belongs in traces and logs, not metrics. Metrics answer "how many, how fast, how often" in aggregate; traces answer "what happened to this particular request". Trying to make metrics answer per-entity questions is what causes the explosion.
Defences: enforced allow-lists on labels, cardinality limits at the collector, and alerting on series growth so the explosion is caught in staging rather than in production.