Error Tracking & Monitoring

High Cardinality Data: Why It Matters for Observability

Understand cardinality in observability: why high-cardinality dimensions explode costs and how to manage them without losing visibility into your systems.

If you've scaled a microservice architecture, you've probably encountered cardinality warnings in your observability platform—or worse, a surprise bill. High cardinality data is one of the most misunderstood cost drivers in modern observability. Understanding what it is, why it matters, and how to manage it can be the difference between a functional observability system and one that bankrupts your DevOps budget.

Cardinality in observability refers to the number of unique combinations of tag and label values across your metrics, traces, or events. A single endpoint might seem simple, but add dimensions like user ID, request ID, customer tenant, API version, and error code, and you quickly have thousands (or millions) of unique combinations. This explosion of combinations is where costs skyrocket and query performance degrades.

What Is Cardinality in Observability?

At its core, cardinality is a measure of uniqueness. If your http_status_code dimension has 10 possible values (200, 201, 204, 400, 401, 403, 404, 500, 502, 503), it has a cardinality of 10. When you combine dimensions, the total cardinality becomes the product of all combinations.

Consider a real example: an API endpoint serving 50 different customers, returning 10 HTTP status codes, and deployed in 5 regions. The potential cardinality of that one metric is 50 × 10 × 5 = 2,500 unique combinations. Now multiply that across 100 endpoints and dozens of metrics, and you're seeing millions of individual time series stored, indexed, and queried separately.

The challenge is that developers often don't realize they're creating high-cardinality data. A metric like request_duration{user_id, endpoint, customer_id, error_reason} seems reasonable until you have millions of unique users and every error condition creates a new combination. Observability platforms charge by the volume of unique time series ingested, so high cardinality directly drives costs.

Not all high-cardinality dimensions are equal. User IDs and request IDs are almost always too granular—they create millions of unique combinations with little diagnostic value. Customer tenant or feature flag status, on the other hand, often justify the cardinality cost because they reveal patterns across your business.

The Cost Trap: Why High Cardinality Explodes Bills

Observability platforms—whether error tracking, metrics, or tracing systems—typically charge based on ingestion volume. A unique combination of tag values counts as a discrete billable unit. If you're paying by the million events, a system generating 1 billion events monthly from 10 million unique combinations costs very differently from one generating the same volume from 100,000 combinations.

The real problem compounds over time. High-cardinality data doesn't just increase costs; it degrades system performance. Queries spanning millions of combinations take longer. Alerting rules become harder to write (how do you alert on one specific combination among millions?). The observability system becomes expensive to run and difficult to use.

This is why successful teams adopt cardinality budgets early. A cardinality budget is a hard constraint: "We will ingest no more than 100,000 unique combinations per metric." Enforcing this budget upstream—at the application layer—prevents problems downstream. It's far cheaper to drop a problematic label at the source than to pay for ingesting and querying millions of unnecessary combinations.

Cardinality Across Observability Pillars

Cardinality impacts different observability types differently. In metrics (Prometheus, Grafana Loki), cardinality is most damaging. These systems are optimized for relatively low-cardinality data with high volume. A single high-cardinality metric can overwhelm the entire platform.

In distributed tracing, cardinality is less of a cost issue but still a usability problem. A trace span has a finite size, so adding tags is less economically punishing. However, high cardinality still matters for error grouping and fingerprinting—when you have millions of unique error signatures from different user IDs or request parameters, grouping becomes noisy and less actionable. This is why observability vs. monitoring emphasizes the role of human-readable dimensions over raw uniqueness.

In error tracking, cardinality affects both cost and signal quality. If every error is tagged with a unique request ID, you can't see patterns across different user sessions. But if you drop all context, debugging becomes nearly impossible. The balance requires intentional choices: tag by customer, feature, or API version—dimensions that help you understand what happened and to whom.

Use the 80/20 rule for cardinality: 20% of your dimensions probably account for 80% of your actual debugging needs. Identify those high-value dimensions and drop the rest.

Practical Strategies for Managing Cardinality

Avoid unbounded dimensions. Never tag with user ID, request ID, session ID, or any identifier that grows with your user base. These are classic cardinality traps. If you need per-user debugging, use span attributes or baggage—metadata that's visible when inspecting a specific trace but not indexed for querying.

Use labels strategically. Tag by categories that matter: environment (prod, staging, dev), customer tier (free, pro, enterprise), region, API version. These grow predictably and help you understand system behavior across cohorts.

Implement sampling and rollups. For very high-volume systems, sample traces instead of capturing every one. Keep 100% of error traces and 10% of successful ones. Aggregate metrics by time window rather than storing every raw data point. This reduces cardinality without losing visibility.

Enforce cardinality budgets at the source. The best place to prevent high-cardinality data is at the application layer, before it leaves your process. Use instrumentation that validates tags before shipping and fails fast on cardinality violations.

Monitor cardinality itself. Most observability platforms expose metrics about unique value counts. Track these actively. A spike in cardinality is a signal that something new is being tagged—investigate immediately.

Here's a realistic code example showing the distinction between indexed tags and safe attributes:

const Sentry = require("@sentry/node");

Sentry.init({
  dsn: "https://<key>@light-trace.robomiri.com/1",
  tracesSampleRate: 0.1, // Sample 10% of transactions
});

const transaction = Sentry.startTransaction({
  name: "GET /api/orders",
  op: "http.server",
});

const span = transaction.startChild({
  op: "db.query",
  description: "SELECT * FROM orders",
});

// Low-cardinality tags: safe to index and aggregate
span.setTag("db.system", "postgres");
span.setTag("http.status_code", 200);
span.setTag("environment", "production");
span.setTag("customer_tier", "enterprise"); // bounded: 3-5 values

// High-cardinality data: store as attributes, not tags
span.setData("user_id", request.user.id);
span.setData("customer_id", request.customer.id);
span.setData("order_id", request.params.orderId);

span.finish();
transaction.finish();

The critical distinction: setTag() indexes the field (searchable, queryable, expensive); setData() stores it in the span (visible in detail view, not indexed).

Cardinality in Your Observability Strategy

Error tracking best practices and cardinality management are inseparable. If you tag every error with unique identifiers, you end up with thousands of error fingerprints for the same underlying bug. This is where intelligent error grouping solves the problem—it finds the root cause and groups similar errors together, regardless of surrounding cardinality.

As you mature through the observability maturity model, cardinality becomes a core design concern. Early on, you care whether errors are flowing in. Later, you need to trace requests end-to-end and understand causation across services. Scaling that maturity requires deliberate cardinality choices. The teams that win treat cardinality as a first-class design tradeoff from day one.

When using tools like LightTrace for distributed tracing and error tracking, you get built-in support for this balance. You capture full stack traces, breadcrumbs, and rich context without needing to index high-cardinality data separately. The platform handles intelligent sampling so you keep visibility on what matters—errors and slow transactions—without the cost spiral of unbounded metrics cardinality.

Cardinality management isn't a one-time task. As your system grows and traffic patterns change, revisit your instrumentation strategy quarterly. What worked at 100 requests per second might cause cost explosions at 10,000 req/s.

Practical Cardinality Boundaries

Here are sane defaults for production systems:

  • Indexed tags per metric: 10-15 maximum, each with under 100 unique values
  • Trace sampling: 10-50% of all traces (100% for errors)
  • Span baggage: Unlimited; use for user, request, and session context
  • Total dimensions: Treat 5 core dimensions (service, environment, version, method, status) as your baseline

These aren't universal rules—your scale and cost tolerance might differ. But they prevent the most common cardinality disasters and keep query performance reasonable.

The bottom line: cardinality is invisible until it isn't. You'll know you've missed the problem when your observability bill arrives, or your platform grinds to a halt under millions of unique combinations. By understanding what drives cardinality and managing it intentionally, you build an observability system that scales with your business and reveals real insights instead of noise.

Start tracking errors in minutes

Ready to build an observability system that scales without cardinality-driven costs? Try LightTrace free—get Sentry-compatible error tracking and distributed tracing designed to help you manage cardinality intelligently.

Fix your next production error faster

Point any Sentry SDK at LightTrace — free up to 5,000 events/month.