Cardinality, in the context of metrics systems and observability pipelines, refers to the number of unique combinations of label or tag values attached to a metric or event stream. A cardinality explosion, sometimes called a cardinality blowup or high-cardinality event, happens when those unique combinations multiply so fast that the indexing, storage, and query layers built to manage them collapse under the load. In a system like Prometheus, each unique combination of metric name and label set creates a distinct time series, so adding a single label such as user_id or request_id to a widely used metric can multiply active series counts by millions overnight.
Organizations care because the consequences hit simultaneously across cost, performance, and reliability. Prometheus stores its TSDB index in memory, so a cardinality explosion translates directly into out-of-memory crashes and ingestion failures. On the cost side, Datadog bills custom metrics based on the number of distinct tag-value combinations, which means a developer who attaches a customer_id label to a high-frequency metric can generate a billing surprise before the next morning standup. Understanding cardinality explosion is therefore a prerequisite for anyone designing schemas, labeling strategies, or ingestion pipelines at scale.
Key Takeaways
- Cardinality explosion occurs when unbounded label values multiply unique time series or index entries faster than storage and memory systems can absorb them.
- High-cardinality data such as user IDs, request IDs, and raw URLs belongs in log analytics or trace storage, not in metric label sets.
- Schema design choices made at ingestion time, specifically which fields get indexed, determine whether a pipeline scales or collapses.
Metrics systems use inverted indexes keyed on label sets, so cardinality multiplies the number of indexed entries held in memory. VictoriaMetrics documentation quantifies this directly, noting that active time series determine RAM usage and that production deployments typically need roughly 1 KB of RAM per active time series. A deployment sitting at 10 million active series therefore needs 10 GB of RAM just for the index before it processes a single query.
Query performance degrades alongside memory pressure. When a query planner must scan or merge millions of series to return a result, latency climbs and compute costs follow. Grafana Mimir identifies cardinality as a primary scalability limiter and ships a dedicated cardinality analysis API specifically because diagnosing explosion events in production is otherwise opaque and slow.
The structural problem is that high-cardinality identifiers defeat the purpose of aggregation-oriented metrics entirely. A trace_id used as a metric label does not aggregate; it just bloats. The OpenTelemetry specification explicitly warns against using high-cardinality values such as URLs and user IDs as metric attribute keys, recommending those values live in trace spans or log records instead. Log systems store raw records and build indexes per field at query time using columnar compression; high-cardinality string fields compress efficiently through dictionary and run-length encoding and do not cause memory exhaustion the way metric indexes do.
Several domains generate cardinality explosions predictably. Kubernetes environments produce per-pod, per-container, and per-node labels that churn frequently as deployments scale and restart. CDN and edge analytics pipelines attach per-URL, per-IP, and per-point-of-presence dimensions to high-frequency event streams. Multi-tenant SaaS products often instrument shared metric pipelines with per-customer dimensions without realizing each new customer multiplies every labeled metric. Security and SIEM pipelines index per-source-IP and per-user-agent labels on event counters that see enormous variety. The CNCF TAG Observability whitepaper identifies cardinality as a first-class operational concern across all of these cloud-native contexts.
Most teams encounter three recurring obstacles when addressing cardinality explosion.
The first is late detection. Cardinality grows incrementally: a new feature ships with an extra label, a new tenant onboards, a new endpoint gets instrumented. The problem only becomes visible when memory pressure triggers an alert or a bill arrives. By that point, the label is already baked into dashboards, alerts, and downstream consumers, making it expensive to remove.
The second hurdle is the instinct to index everything. Developers coming from relational database backgrounds often assume that adding a column or a tag is cheap. In metric TSDBs and certain log platforms, indexing a high-cardinality field is structurally expensive. Prometheus best practices explicitly list email_address, user_id, and url as labels that should not be used because they cause cardinality explosion, but that guidance does not always reach the teams writing instrumentation code.
The third hurdle is federation and fanout. In distributed Prometheus setups using Thanos or similar federation layers, label cardinality affects shard planning and query fanout, meaning a cardinality problem in one cluster propagates latency across the entire federated query path.
Preventing cardinality explosion starts at schema design and ingestion time, not after a crisis.
First, audit which fields actually need indexing before writing them into a metric label set or a log index schema. Fields that identify individual requests, users, or sessions belong in the row payload as non-indexed columns, not in the primary dimension schema. Storing them in a data lake or columnar store rather than a TSDB index preserves queryability without the memory cost.
Second, use pipeline-layer mitigation. The OTel Collector supports processors that delete, hash, redact, or aggregate high-cardinality attributes before data reaches the backend. The OTel SDK itself enforces a default cardinality limit of 2,000 unique attribute sets per instrument, dropping overflow series to protect downstream systems. Configuring these limits deliberately rather than relying on defaults gives teams explicit control.
Third, apply pre-aggregation patterns at the source. Prometheus recording rules, OTel delta temporality, and rollup-before-write designs all reduce unique series counts before data lands in storage. Partitioning on low-cardinality dimensions such as region, service name, and environment, while keeping high-cardinality identifiers in the row body, is the architectural pattern that separates pipelines that scale from those that crater. Teams building or evaluating storage infrastructure for high-cardinality telemetry workloads should review the product capabilities and technical documentation relevant to their ingestion schema design.
How does cardinality explosion in metrics differ from high-cardinality fields in log systems?
Metrics systems hold their label-set indexes in memory, so cardinality directly multiplies in-memory index entries and causes memory exhaustion. Log and columnar storage systems write raw records and rely on dictionary encoding and run-length encoding to compress high-cardinality string fields efficiently, so a field with millions of unique values does not carry the same memory penalty. That architectural difference is why high-cardinality identifiers belong in logs or traces rather than metric label sets.
How does the OpenTelemetry collector reduce cardinality before data reaches a backend?
The OTel Collector's `attributes` processor can delete, hash, or redact high-cardinality label values in the pipeline before export. The `metricstransform` processor can aggregate away entire dimensions, and SDK-level limits drop overflow series at the application boundary. These layers let platform teams enforce cardinality budgets without requiring every development team to change their instrumentation code.
What schema design practices prevent cardinality explosion at ingestion time?
Never index unbounded fields such as UUIDs, session tokens, or raw URLs in the primary dimension or tag schema; store them as non-indexed payload columns instead. Apply hashing or bucketing to continuous numeric dimensions, partition on low-cardinality fields such as region and environment, and enforce schema-at-write validation to reject unexpected high-cardinality fields before they propagate into the index. Pre-aggregation before write further reduces the unique series count that storage systems must manage.
How does cardinality explosion affect observability SaaS billing?
Most commercial platforms bill on either the count of distinct metric time series or total ingested data volume, both of which scale directly with cardinality. Adding a single `customer_id` tag to a metric instrumented across 20 services multiplies billable series by the total number of unique customers, often producing a cost increase that outpaces any infrastructure savings. Enforcing tagging policies at the collector layer and routing high-cardinality event data to log or object storage backends rather than a TSDB are the most direct controls available.