Infrastructure

Cardinality is the number that decides the bill

Series count is the product of label values rather than the sum, so one line of code can multiply an invoice by five figures.

For a separate operational view of time, ownership and team activity, see the Monitask overview.

If a monitoring invoice has ever arrived at a number nobody could explain, this is usually the reason. Cardinality is the count of distinct series a system is storing, and it behaves in a way that surprises people because it multiplies rather than adds.

The arithmetic

A measurement carries labels. Each label has some number of possible values, and the number of series is the product of them all, not the sum.

Five endpoints, four methods and three status classes produce sixty series. That is entirely manageable, and it is what most examples in documentation look like.

Now somebody adds a customer identifier, because it would be useful to see which customer is affected. If there are a hundred thousand customers, the sixty becomes six million. The change was one line in an application, it passed review because it looked like a small improvement to observability, and it multiplied the storage, the memory and the bill by five figures.

What each series actually costs

An index entry, because the system must be able to find it. Memory in whatever component holds recent data, which is usually the binding constraint before storage is. Storage for its samples for as long as retention says. And query time proportional to how many series a query has to touch, which is why dashboards get slow before they get expensive.

Most commercial pricing in this market is built on some form of series or custom metric count, which is why the effect appears on an invoice rather than in a capacity graph.

The labels that do the damage

Anything unique per request or per person: request identifiers, session identifiers, user or customer identifiers, email addresses, full paths containing an identifier, and error messages used as a label, which is unbounded because messages contain values.

And anything unique per instance in an environment that replaces instances constantly. A pod name looks like a small set until a deployment happens, at which point the old series do not disappear, they merely stop receiving samples. The count that matters over a month is not how many exist now but how many have existed, and a system that redeploys ten times a day accumulates them relentlessly.

This last one is the quiet version. There is no single bad decision to point at, and the graph of series count climbs gently until something falls over.

5endpointx4methodx3status=60then somebody adds one more label100 000customer id=6 000 000one line of code, not a setting
Figure 1Three modest labels give sixty series. One identifier label multiplies that into millions, and the change looks like a small improvement in a code review.

The tension is real, and it resolves by routing

The awkward part is that high-cardinality questions are exactly the useful ones. Which customer, which request, which build: those are the questions asked during an incident, and they are the ones cardinality limits forbid.

The resolution is not to fight it but to send it to the right shape. Metrics carry the low-cardinality dimensions that alerting needs: is the error rate up, on which service, in which region. The high-cardinality detail lives in events, logs or traces, where per-record identifiers are the normal condition rather than an explosion, and where the cost model is built for it.

Put another way, a system with a customer identifier in a metric label is usually a system whose owner needed a trace and reached for a counter.

Making it visible before it is expensive

Three practices cover most of it. Look at the series count by metric name regularly, because the offender is almost always a single name holding a large share of the total. Drop or rewrite labels at the collection point, which works even when the application cannot be changed. And set a limit that refuses new series past a threshold, so that the failure is a rejected metric rather than an invoice.

The organisational version matters more than any of them: label choices belong in code review, and a reviewer who has seen this once will catch it in the diff, which is the only place it is cheap to catch.

The same shape on the other side

Workforce tools have their own version, usually as per-seat pricing multiplied by feature tiers and retention. It is less dramatic arithmetically and behaves the same way at purchase: the number that determines the invoice is not the one on the front of the quote, and it is decided by a configuration choice made after signing.

What we cannot verify

The counts used above are illustrative, chosen to show the multiplication rather than measured anywhere. Pricing models are published by vendors, differ substantially between them, change, and frequently distinguish between categories in ways that only become apparent on an invoice. We quote no rates. What a specific system costs is answerable only from that system's own series count, which is worth looking at before rather than after.

The short version

  1. Series count is the product of label values, not the sum.
  2. One identifier label can multiply sixty series into six million.
  3. Memory in the ingest path binds before storage does, and query time follows series touched.
  4. Ephemeral instance names accumulate series that stop receiving samples but do not leave.
  5. Route high-cardinality questions to events and traces, not to metric labels.
  6. Label choices belong in code review, which is the only cheap place to catch them.

Further context

Start from the class of problem, not the list of tools

Every selection here names the situation first and the criteria second. Product names come last, and each one carries the line describing what it costs you.