Cardinalidade de métricas: o que é, por que explode custos e como reduzir

Cardinalidade de métricas na observabilidade

Toda conta de observabilidade que sai do controle tem a mesma causa raiz escondida: a cardinalidade de métricas. O termo define quantas séries temporais o backend de monitoramento precisa armazenar, indexar e consultar. Ele parece um detalhe de implementação, mas decide o desempenho e o custo de toda a stack.

Na prática, a cardinalidade explica por que o Prometheus consome gigabytes de memória e por que dashboards demoram para carregar. Ela também explica por que a fatura de plataformas SaaS cresce sem aviso. Um único label mal escolhido pode multiplicar as séries por milhões. O efeito é silencioso até o dia em que o storage estoura.

Neste guia, você vai entender o conceito, calcular a cardinalidade do seu ambiente e medir os ofensores reais. Além disso, vai conhecer as estratégias que times de SRE aplicam para manter as métricas na observabilidade sob controle.

 

O que é cardinalidade de métricas

Cardinalidade de métricas é o número de séries temporais únicas que uma métrica gera. Cada combinação distinta de nome de métrica e valores de labels cria uma série nova no banco de dados. Quanto mais valores cada label admite, maior a cardinalidade e maior o consumo de memória, CPU e armazenamento.

Considere a métrica http_requests_total com os labels method e status. Com 5 métodos HTTP e 10 códigos de status, ela gera até 50 séries. O número parece inofensivo, porém cresce de forma multiplicativa a cada label adicionado.

Vale destacar que o backend não armazena “uma métrica”: ele armazena cada série individualmente. Por isso, sistemas como Prometheus, VictoriaMetrics e Datadog tratam a cardinalidade como a unidade real de capacidade e de cobrança.

 

Como calcular a cardinalidade de uma métrica

A cardinalidade de uma métrica é o produto dos valores distintos de cada label. Multiplique as possibilidades de cada dimensão. Uma métrica com 5 endpoints, 10 códigos de status e 50 hosts gera 5 x 10 x 50, ou seja, 2.500 séries temporais. O cálculo vale para qualquer backend baseado em séries.

Agora adicione um label user_id com 10 mil usuários ativos. As mesmas combinações saltam para 25 milhões de séries. Nenhum upgrade de hardware acompanha esse salto, porque o crescimento é geométrico, não linear.

Esse efeito multiplicativo explica a regra de ouro da instrumentação: cada label novo precisa justificar o custo de todas as combinações que cria.

Um exercício simples ajuda a criar o hábito. Antes de adicionar um label, estime quantos valores ele pode assumir em produção, não em desenvolvimento. Enum com 5 status? Seguro. Nome de cliente em uma base que cresce todo mês? A série vai crescer junto, sem limite.

 

Por que a alta cardinalidade é um problema

Alta cardinalidade é um problema porque cada série ativa ocupa memória, engorda o índice do TSDB e deixa as consultas mais lentas. Em plataformas SaaS, o impacto vira financeiro: fornecedores cobram por série ou por custom metric, então a cardinalidade determina o tamanho da fatura.

No monitoramento com Prometheus, cada série viva consome memória no head block e espaço no índice. Consequentemente, ambientes com milhões de séries sofrem com OOMKills, scrapes atrasados e dashboards que expiram antes de renderizar.

Há também um custo operacional silencioso: queries que varrem milhões de séries penalizam todo o cluster. Um dashboard aberto por cinco pessoas pode derrubar o backend inteiro, justamente durante o incidente que ele deveria ajudar a resolver.

O modelo de cobrança do Datadog ilustra bem o lado financeiro.

Uma custom metric é cada combinação única de nome e valores de tags, como descreve a documentação oficial de billing. O plano Pro inclui 100 custom metrics por host; cada 100 métricas ingeridas acima da franquia custam US$ 0,10.

Não por acaso, o custo lidera a escolha de ferramentas de observabilidade pelo terceiro ano seguido, aponta a pesquisa anual da Grafana Labs.

 

O que causa explosão de cardinalidade

A explosão de cardinalidade nasce de labels com valores ilimitados: identificadores únicos, timestamps, IPs, paths dinâmicos e IDs de pods em clusters Kubernetes. Cada valor inédito cria uma série nova no backend. O problema se agrava em microsserviços, nos quais dezenas de times instrumentam aplicações sem uma convenção comum de labels.

Outra fonte comum é a integração de exporters prontos sem revisão. Um exporter de banco de dados pode expor uma métrica por tabela; um de mensageria, uma por fila. Instalados no padrão, eles despejam milhares de séries que ninguém pediu, sobretudo em ambientes com centenas de instâncias.

A tabela abaixo classifica os tipos de label pelo risco que representam:

 

Tipo de label Exemplos Cardinalidade típica Recomendação
ProibidoIdentificadores únicos user_id request_id trace_id Milhões (ilimitada) Nunca usar como label: mover para logs e traces
Alto riscoValores dinâmicos path completo, IP de origem, timestamp Dezenas de milhares Normalizar na instrumentação antes de expor
AtençãoInfraestrutura elástica pod instance container_id Centenas a milhares Agregar com recording rules e vigiar o churn
SeguroDimensões estáveis method status_code service Unidades a dezenas Padrão recomendado de baixa cardinalidade

 

Repare que o problema raramente é o volume de métricas: é o formato delas. Em suma, 20 métricas bem desenhadas dizem mais do que 2.000 séries geradas por um label de request_id.

Ambientes Kubernetes merecem atenção especial. A cada deploy, os pods antigos morrem e os novos nascem com nomes diferentes, o que renova o valor do label pod. Esse churn acumula séries órfãs: as antigas param de receber dados, mas continuam no índice até expirar a retenção.

 

Como medir e detectar alta cardinalidade

Para medir a cardinalidade, conte as séries ativas do TSDB e identifique quais métricas concentram o crescimento. No Prometheus, o endpoint /api/v1/status/tsdb lista as métricas e labels mais pesados do banco. Além disso, três queries em PromQL mostram em segundos onde a cardinalidade mora no seu ambiente.




query.promql
# Total de séries ativas no TSDB
count({__name__=~".+"})

# Top 10 métricas com mais séries
topk(10, count by (__name__)({__name__=~".+"}))

# Velocidade de criação de séries novas (churn)
rate(prometheus_tsdb_head_series_created_total[5m])

Rode a segunda query toda semana e acompanhe a tendência. Se uma métrica dobra de séries sem mudança no negócio, algum label começou a receber valores dinâmicos. Para dominar essas funções, o guia prático de PromQL detalha os operadores de agregação.

Em stacks com Grafana Mimir ou Grafana Cloud, ferramentas como o Mimirtool listam métricas que nenhum dashboard ou alerta consulta. Eliminar essas séries não usadas costuma ser a vitória mais rápida: corta custo sem tirar nenhuma visibilidade que o time realmente usa.

 

Como controlar e reduzir a cardinalidade

O controle de cardinalidade combina três frentes: labels enxutos na origem, filtro do excesso na coleta e agregação antes do armazenamento de longo prazo. Nenhuma técnica isolada resolve o problema; o resultado vem da disciplina aplicada nas três camadas ao mesmo tempo.

 

Desenhe labels enxutos na origem

A decisão mais barata acontece no código. Durante a instrumentação de aplicações, normalize paths (/users/{id} em vez de /users/12345), limite valores a listas fechadas e nunca use identificadores únicos como label.

A documentação oficial do Prometheus recomenda manter a cardinalidade de cada métrica abaixo de 10. Métricas que passam de 100 séries, ou que têm potencial para isso, merecem investigação imediata.

Adote também as convenções semânticas do OpenTelemetry para padronizar nomes e atributos entre times. Dessa forma, dois serviços nunca criam labels diferentes para a mesma dimensão.

 

Filtre com relabeling e limites de scrape

Quando não dá para mudar o código, o Prometheus filtra na coleta. O metric_relabel_configs descarta labels ou métricas inteiras antes da ingestão, enquanto o sample_limit corta scrapes fora de controle:




prometheus.yml
scrape_configs:
  - job_name: 'app'
    sample_limit: 10000
    metric_relabel_configs:
      # Remove o label de alta cardinalidade
      - regex: 'request_id'
        action: labeldrop
      # Descarta métricas de debug inteiras
      - source_labels: [__name__]
        regex: 'debug_.*'
        action: drop

Trate esses filtros como código de produção: versione o prometheus.yml, revise mudanças em pull request e documente por que cada drop existe. Governança de labels é o que impede a cardinalidade de voltar a crescer seis meses depois da limpeza.

 

Agregue e escolha o backend certo

Recording rules pré-agregam séries detalhadas em métricas resumidas para dashboards e alertas. Assim, você consulta o agregado leve no dia a dia e reserva o detalhe bruto para retenções curtas.

Defina também políticas de retenção por resolução: detalhe completo por 15 dias, agregados por 13 meses. Downsampling entrega a visão histórica de capacity planning sem carregar bilhões de pontos brutos para sempre.

Se o ambiente sustenta milhões de séries mesmo depois da limpeza, avalie backends desenhados para essa escala. O comparativo entre VictoriaMetrics e Prometheus mostra quando a troca compensa em memória e compressão.

 

Alta cardinalidade é sempre ruim?

Alta cardinalidade não é sempre ruim: ela é prejudicial no lugar errado. O detalhe que explode uma métrica é o mesmo que resolve uma investigação, como saber qual usuário ou request falhou. A questão é onde guardar esse detalhe: em logs, traces e exemplars, não em labels de métricas.

Métricas respondem “o quê” e “quanto”; logs e traces respondem “quem” e “por quê”. Portanto, mova identificadores únicos para os sinais que absorvem alto volume por natureza e mantenha as métricas agregadas.

Exemplars são o elo entre os dois mundos: amostras anexadas aos buckets de histograma que apontam para um trace específico. Com eles, a métrica continua agregada, mas a investigação chega ao request problemático em um clique.

Uma plataforma de observabilidade bem arquitetada conecta os três sinais. A métrica dispara o alerta, o exemplar aponta o trace e o trace revela o request exato. Cada dado mora onde custa menos e rende mais.

 

Observabilidade & OpenTelemetry

Logs, métricas e traces unificados para diagnóstico em profundidade.

Instrumentamos aplicações corporativas com OpenTelemetry para correlacionar eventos e acelerar a análise de causa raiz em produção.

Fale com um Especialista →

 

Conclusão

Cardinalidade de métricas deixou de ser um detalhe técnico para virar uma decisão de arquitetura e de orçamento. Cada label define quantas séries o backend sustenta, quanta memória o Prometheus consome e quanto a fatura SaaS cresce no fim do mês.

O caminho para o controle é claro. Primeiro, entenda o cálculo: labels multiplicam séries de forma geométrica. Em seguida, meça o ambiente com as queries deste guia e encontre os ofensores reais. Por fim, aplique a disciplina nas três camadas: labels enxutos na origem, relabeling na coleta e agregação no armazenamento.

O resultado aparece rápido: consultas mais leves, dashboards estáveis e uma conta de observabilidade previsível. Sobretudo, sobra capacidade para instrumentar o que realmente importa para o negócio.

Sua operação sofre com consumo de memória, consultas lentas ou custos crescentes de monitoramento? Fale com um especialista da OpServices e descubra como estruturar uma estratégia de métricas com cardinalidade sob controle.


 

Perguntas Frequentes

O que é cardinalidade de métricas?
Cardinalidade de métricas é o número de séries temporais únicas que uma métrica gera. Cada combinação distinta de nome de métrica e valores de labels cria uma série separada no banco de dados. Uma métrica com labels de método HTTP, código de status e host, por exemplo, gera uma série para cada combinação possível desses valores. Quanto maior a cardinalidade, maior o consumo de memória, armazenamento e CPU do sistema de monitoramento.
Quais labels devem ser evitados em métricas?
Evite labels com valores ilimitados ou únicos: user_id, request_id, session_id, UUIDs, timestamps, endereços IP e paths dinâmicos de URL. Cada valor novo cria uma série temporal nova, o que multiplica o consumo de recursos. Prefira labels estáveis e de baixa cardinalidade, como método HTTP, código de status, nome do serviço e região. Identificadores únicos pertencem a logs e traces, não a métricas.
Alta cardinalidade é sempre ruim?
Não. Alta cardinalidade é prejudicial quando está no lugar errado: em labels de métricas, ela multiplica séries e custos sem necessidade. O mesmo nível de detalhe é valioso em logs, traces e exemplars, sinais desenhados para absorver alto volume de valores únicos. A prática recomendada é manter métricas agregadas para alertas e tendências e usar os demais sinais para investigação detalhada.
Qual a diferença entre cardinalidade em métricas e em logs e traces?
Em métricas, cada combinação de labels vira uma série temporal permanente na memória e no índice do backend, então o custo cresce de forma multiplicativa. Logs e traces gravam valores únicos como eventos individuais e os indexam sob demanda, o que absorve alta cardinalidade com custo muito menor. Por isso, identificadores únicos devem viver em logs e traces, enquanto métricas ficam com dimensões estáveis e agregadas.

Trabalho há mais de 15 anos no mercado B2B de tecnologia e hoje atuo como Gerente de Marketing da OpServices e Líder em Projetos de Governança para Inteligência Artificial.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

plugins premium WordPress