In this lesson, you will learn how to prevent system performance degradation and storage explosions by managing high-cardinality data in your metric instrumentation.
What is High Cardinality?
In observability, "cardinality" refers to the number of unique combinations of values for your metric tags (labels). If you have a metric like http_request_duration_seconds, a low-cardinality tag might be method (GET, POST, etc.). A high-cardinality tag, however, would be user_id or request_uuid.
If you have 10,000 active users, a metric tagged with user_id creates 10,000 unique time series for every single instrumented event. In a distributed Node.js environment, this causes massive memory pressure on your process and can crash your metrics backend (like Prometheus or InfluxDB), as it struggles to index an infinite number of series.
The Performance Impact
When you push high-cardinality metrics, your Node.js event loop often slows down due to the memory overhead required to track these unique metric instances in the registry. Your metrics library has to maintain a hash map of every seen tag combination, which grows indefinitely until your heap is exhausted.
Mitigation: Use "Bucketing" and "Drop-by-Design"
Instead of tracking unbounded data, you must force constraints on your labels. If you need to track user behavior, use categories rather than raw IDs.
// AVOID: High-cardinality
// This creates a new metric series for every unique user!
metrics.counter({
name: 'http_requests_total',
labels: ['user_id']
});
// PREFER: Low-cardinality categorization
// Use a user-tier or status group instead
metrics.counter({
name: 'http_requests_total',
labels: ['user_tier'] // e.g., 'free', 'premium', 'enterprise'
});
When building custom metric collectors, always enforce an allow-list for tag values. If a tag value is dynamic (like a path parameter /users/:id), strip the ID before incrementing the metric to ensure the label remains constant (e.g., /users/:id rather than /users/123).
Key Takeaway: Never include unbounded identifiers like User IDs or Request UUIDs as metric labels; categorize dynamic data into finite, predefined groups to protect your system's memory and indexing performance.