Cardinality là số chuỗi thời gian (time series) riêng biệt mà một metric sinh ra.
Với Prometheus, mỗi tổ hợp giá trị label là một chuỗi riêng, lưu riêng, đánh chỉ mục riêng.
http_requests_total{route="/orders", status="200"} # vai chuc chuoi
http_requests_total{route="/orders", user_id="u_1"} # bang so userMetric đầu có route (vài chục) nhân status (vài giá trị) → vài trăm chuỗi. Metric sau nhân thêm số người dùng — một triệu user là một triệu chuỗi, và mỗi user mới lại tạo chuỗi mới vĩnh viễn. Hệ quả: bộ nhớ của Prometheus tăng vọt, truy vấn chậm dần rồi timeout, cuối cùng instance monitoring hỏng trước cả service mà nó theo dõi.
Nguyên tắc: label chỉ dùng cho giá trị có tập hợp nhỏ và bị chặn — route, method, status_code, env, region. Không dùng: user_id, email, order_id, request_id, trace_id, URL đầy đủ còn nguyên query string, thông điệp lỗi tự do.
Vậy chi tiết theo user đặt ở đâu? Ở log và trace — hai loại này vốn dành cho dữ liệu cardinality cao: đặt user_id làm trường log hoặc span attribute rồi truy vấn theo nó. Metric để tổng hợp, log/trace để tra cứu từng trường hợp.
Một biến thể hay gặp: route lấy nguyên đường dẫn thật (/orders/8831) thay vì mẫu (/orders/:id) — cũng làm nổ cardinality y hệt.