Metrics

Metrics are the cheapest, most efficient telemetry you have — a handful of numbers that summarize millions of events and tell you, at a glance, whether your system is healthy. Their power is aggregation; their trap is cardinality; and knowing which numbers to watch (and how to read percentiles) is the difference between a dashboard that warns you and one that lies to you.

The last post named metrics as the pillar that answers “is something wrong, and how much?” This post goes deep: what metrics are, the main types, the percentile trap that fools teams into thinking they’re fine, the cardinality problem that blows up costs, and the frameworks (RED, USE) for choosing what to measure. Metrics are where observability usually starts, because they’re cheap to collect and superb at detection.

What a metric is

A metric is a numerical measurement tracked over time — a time series of values with a timestamp. “Requests per second,” “error count,” “memory used,” “request latency” are metrics. Their defining property is aggregation: a metric doesn’t record every individual event, it records summaries (counts, sums, distributions) at intervals. This is exactly why metrics are so efficient — a single number can represent millions of underlying events, so metrics are cheap to store, fast to query, and ideal for dashboards and trends over long time ranges.

The trade-off of aggregation is lost detail: a metric tells you the error rate jumped, but not which requests failed or why (that’s logs and traces). So metrics are the detection and trend layer — great for “something is wrong, here’s how much, here’s the trend,” and deliberately not for “here’s exactly what happened.” Play to that strength.

The metric types

Most metric systems (Prometheus-style) have a few fundamental types, and using the right one matters:

Choosing correctly: counters for things that accumulate (requests, errors), gauges for current levels (memory, connections), histograms for anything where the distribution matters (latency, sizes). Using a gauge where you need a rate, or an average where you need percentiles, produces misleading dashboards.

The percentile trap: why averages lie

The most important practical lesson about metrics: do not measure latency (or any user-experience metric) with averages — use percentiles. An average latency hides the tail, and the tail is where users suffer:

100 requests: 99 take 50ms, 1 takes 5000ms
  average latency = ~100ms   ← looks fine!
  p99 latency     = 5000ms   ← one in a hundred users waited 5 seconds

The average says 100ms and looks healthy; meanwhile 1% of users had a terrible experience. Percentiles tell the truth: p50 (median) is the typical case, p95/p99 are the tail — what your worst-served users experience. At scale, “1% of requests” is a lot of real, unhappy users, and often includes your most active ones (more requests = more chances to hit the tail). Always dashboard and alert on p95/p99 latency, not averages — averages are the single most common way metrics dashboards lull teams into thinking a struggling system is fine. This is why histograms matter: they’re what let you compute percentiles at all.

The cardinality trap: why metrics blow up

Metrics get powerful when you attach labels (dimensions) — tag a metric by endpoint, status code, region, so you can slice it (“error rate for the checkout endpoint in us-east”). But this is also metrics’ main danger: cardinality. Each unique combination of label values creates a separate time series, and the count multiplies:

requests{endpoint, status, region}
  10 endpoints × 20 statuses × 5 regions = 1,000 time series   ← fine
  ...add user_id (1,000,000 users) → 1,000,000,000 time series ← catastrophe

The killer mistake is putting high-cardinality values in labels — user IDs, request IDs, email addresses, full URLs with parameters. Each unique value spawns a new time series, and unbounded label values (like a user ID) create effectively infinite series, exploding storage and cost and often crippling the metrics system. The rule: labels must be low-cardinality — bounded sets like endpoint, status class, region, not unbounded identifiers. High-cardinality data (which request, which user) belongs in logs and traces, not metric labels. Cardinality is the number one way teams accidentally make their metrics bill (and their metrics database) explode.

What to measure: RED and USE

Rather than measuring randomly, two well-known frameworks tell you which metrics matter:

Together: use RED for your services (the request path users experience) and USE for the resources underneath them. Starting from these frameworks means you measure the things that actually indicate health, rather than a random pile of metrics that look busy but don’t tell you when users are hurting.

Using metrics well

Metrics are the efficient front line of observability — cheap, fast, and perfect for detection and alerting. But when a metric tells you something’s wrong, you need the granular story, which is the next pillar: logs.

Key takeaways

Further reading

Sources & References

Counters, gauges, histograms