Cardinality and the four signals
Why is label cardinality the cost model of metrics, and what does each signal preserve and lose?
Cardinality is the cost model
Cardinality means the number of distinct values. The number of series a metrics system stores is the product of the cardinalities of its labels. A label (or tag) is a key-value pair attached to a metric, like status="200". A series is one unique combination of metric name and label values, and it has its own time-ordered stream of values plus an index entry.
This is the granularity mismatch → amplification law at the metadata layer: a per-request identifier is forced into a per-aggregate structure. Storage is amplified by the cardinality ratio.
The rule that follows is mechanical, not a matter of style:
The real taxonomy: four (plus one) signals
You may have heard of "the three pillars" (metrics, logs, traces). That is a marketing frame, not a real distinction. The signals actually differ on two axes: how cost scales with the number of events, and whether identity survives.
| Signal | Cost scaling | Preserves | Loses |
|---|---|---|---|
| Metrics | O(number of series), independent of event rate | aggregate shape | identity, causality |
| Logs | O(events × bytes) | identity, detail | structure (unless you impose it), the population view |
| Traces | O(sampled events × spans) | causal relationships | population (you keep a few percent) |
| Profiles | O(sample rate), independent of load | resource attribution | time ordering |
| Change events | O(number of deploys), almost nothing | what humans did | everything else |
Reading the table: a metric costs the same at 10 requests per second as at 10,000 (the series count is what matters). A log costs more with every event. That is why metrics are cheap and logs are expensive, and why four types exist.
Change events: the fifth signal
Change events are markers for deploys, config changes, schema changes and upstream DDL (changes to table structure), overlaid on every time series chart. They are nearly free to emit (one record per deploy) and extremely valuable: the prior probability that an incident began with a change is high, so "what changed in the last hour?" resolves more incidents than any detector.
{"ts":"2026-03-05T14:02:11Z","type":"deploy","service":"daily_revenue_job",
"version":"v2.4.0","author":"nadia","change":"new currency conversion"}Checking a change before readers see it (write-audit-publish, shadow runs and data diff) is data quality's subject; a change event is what lets you find the change after a fault.
RED and USE
Two common ways of choosing metrics:
- RED: Rate, Errors, Duration. It is request-centric: for every service, count requests, failures, and how long they take.
- USE: Utilization, Saturation, Errors. It is resource-centric: for every resource (CPU, disk, a connection pool), how busy it is, how much work is waiting, and how many errors.
Both assume a request or a consumable resource. A batch pipeline has neither in the relevant sense. It has arrivals (a file lands, a batch is triggered), not requests. This is exactly why the data-state observables in Data-state observables form their own family and are not an application of RED.
One line: a counter survives loss, a gauge aliases, a histogram fixes its resolution before the question, and the series count is the product of the labels.