SOFTWARE / SYSTEMS / AIEngineering news. Technical depth.
Architecture / 3 MIN READ

Set a cardinality budget before metrics labels set the bill

Keep bounded diagnostic dimensions in metrics, move identities to traces or logs, and enforce label budgets before production traffic arrives.

A metric label belongs in production only when its values are bounded, operationally useful, and cheap enough at expected scale. User IDs, request IDs, raw URLs, email addresses, and unconstrained error text should go to logs or traces. Decide that before instrumentation ships, because one attractive label can multiply every time series.

Estimate series, not label count

Cardinality grows from combinations. A metric with 20 routes, 8 status classes, 5 regions, and 4 versions can create 3,200 active series before replicas and transient values enter the picture. Inventory each proposed label, its maximum distinct values, whether users control it, how values expire, and which dashboard or alert needs it. Multiply plausible combinations rather than adding the columns.

The Prometheus metric and label naming guidance says labels should not represent high-cardinality dimensions such as user IDs or email addresses. It also recommends that one metric represent one logical thing. Those constraints improve both cost and interpretability: a label that changes the meaning of the measurement may deserve a separate metric.

Set budgets at three levels: per instrument, per service, and per tenant or team. Include headroom for deployments and incidents, when novel error values often appear. Require review when a new label could exceed its instrument budget. A schema check can reject known-dangerous names, but runtime limits must catch unanticipated values.

Preserve investigation paths without identities in metrics

Metrics answer how much and when; traces and logs explain which request. Aggregate by stable route template, not raw path. Use error class, not full message. Record a trace exemplar or correlation identifier in the observability backend when supported, so an engineer can jump from an unusual histogram bucket to representative traces without creating a time series per request.

The OpenTelemetry metrics semantic conventions set common naming and attribute expectations and discuss requirement levels for metric attributes. Treat those conventions as a starting schema, then apply your local budget. A standardized attribute can still be inappropriate if your backend or traffic pattern makes its value space unsafe.

For a customer-specific investigation, query logs or traces under access controls and retention policies suited to that data. Do not promote a customer identifier into a permanent metric label because one incident made it convenient. If per-customer service levels are a product requirement, aggregate deliberately into a bounded reporting system rather than accidentally materializing every customer across every metric.

Enforce the budget in the pipeline

Collect active-series counts by metric and label, plus the rate of new values. Alert on sudden growth and identify the latest deployment. Apply allowlists for route names and error classes. Drop or rewrite attributes at the collector when values are untrusted, but fix the source instrumentation too; silent dropping can make developers believe a dimension exists.

When a label exceeds budget, decide whether to remove it, bucket it, aggregate earlier, sample it into traces, or create a separate low-frequency event. Document the lost query before changing it so operators retain an alternative investigation path.

Start with the twenty metrics producing the most active series. For each, write the series estimate, the dashboard or alert that consumes every label, and the log or trace path that replaces any removed identity. Set one enforceable per-instrument limit and rehearse what happens when it is exceeded.

Test hostile label values

Send unique paths, user agents, tenant names, exception messages, and query strings through staging. Confirm instrumentation reduces them to bounded route and error classes before export. Simulate a new deployment value and process identifier on every restart. The collector should preserve useful version grouping without allowing ephemeral identity to multiply long-lived metrics. Measure active series during the test and make budget rejection visible to the owning team.

Reviewed September 2026.

SOURCES & REVIEW

Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.

Read our editorial approach ↗