O seu pipeline de medição perde eventos no pico de tráfego e os números de atribuição nunca batem com os logs do bidder. São duas falhas por trás de um sintoma: eventos que nunca chegaram, em uma costura que ninguém contou, e eventos que chegaram e foram contados sob uma regra diferente. É assim que as costuras, as chaves, a janela de atraso e a ponte de reconciliação são construídas.
Um pipeline de eventos que perde eventos no pico de tráfego e nunca reconcilia com os logs do bidder pode ser duas falhas sob um sintoma. Uma é de transporte: eventos criados e que nunca chegaram, em uma costura que ninguém contou. A outra é definicional: eventos que chegaram e foram contados sob uma regra diferente da do registro do leilão.
O enquadramento habitual - o pipeline descarta eventos, então reconstrua o pipeline - conserta no máximo um deles. O que vem a seguir separa os dois e diz o que uma reconciliação produz, que não é igualdade. Os padrões citados abaixo são os do Kafka no lado do transporte e os do ClickHouse no lado do armazenamento.
A resposta curta é estrutural: um identificador por leilão carregado de ponta a ponta, um contador dos dois lados de cada salto, e uma reconciliação sobre uma janela que já fechou. O que a amBrain pode sustentar publicamente é o trabalho em AdTech: desenvolvimento de DSP, plataformas de real-time bidding e engenharia de ad exchange. Em qualquer stack de RTB, esse é o lado de onde vêm os registros de lance, vitória e impressão. O pipeline abaixo é descrito a partir da mecânica do problema, não de um caso nosso.
A primeira falha é a perda: o evento foi criado e nunca chegou, em um salto específico, por um motivo específico. Um beacon que nunca saiu da página, um edge reiniciado no meio do deploy, um buffer de producer que encheu, um consumer que fez commit do offset antes de processar.
A segunda não é uma falha, de forma alguma. O lado da medição conta um evento iniciado no cliente; o bidder registra um resultado de leilão do lado do servidor. Um é uma adjudicação, o outro é uma observação do que aconteceu com ela. As diretrizes de medição do MRC tratam pre-fetch, pre-render e auto-refresh como coisas separadas a detectar e divulgar: uma regra de contagem, não uma falha de transporte. Distinguir os dois custa uma consulta e alguma paciência.
Enquanto essa curva não existir, os dois lados da discussão são opiniões. Depois, o formato dela decide qual metade deste artigo se aplica, e as metades não são exclusivas.
Há sete lugares onde um evento de anúncio é criado e depois deixa de existir silenciosamente, mais um ajuste que parece uma garantia e não é.
A regra é uma regra de relatório, não de engenharia: uma perda é atribuída a uma costura nomeada, ou não é atribuída de forma alguma. Dois alarmes mantêm as costuras silenciosas visíveis - o lag do consumer medido em tempo contra a retenção, e uma política de reset que falha em vez de pular.
Uma chave de deduplicação não é uma chave primária conveniente escolhida no destino. Ela é atribuída a montante de qualquer retentativa, no momento do leilão ou quando o evento é criado, e o receptor nunca inventa uma. Timestamps de chegada ficam de fora: uma retentativa carrega um novo horário de chegada e uma nova chave.
A chave tem que ser idêntica em toda tentativa, o que decide as partes dela: a exchange ou o seat, o identificador de leilão, o identificador de impressão e o tipo de evento. Particione o tópico por essa chave, para que as retentativas caiam juntas e a ordenação por chave sobreviva a elas. Essa instrução vale só para o transporte: a mesma palavra aplicada ao banco colunar dá uma partição por evento, e o insert morre no limite por bloco. Particione o armazenamento por tempo, ordene pela chave.
Então o formato que funciona é transporte at-least-once com chaves idempotentes. A deduplicação na escrita mantém a conta de armazenamento sã; a deduplicação na leitura é o que deixa o número correto. Merges nunca combinam parts de partições diferentes, então uma duplicata que cai na partição seguinte só é resolvida quando uma consulta pergunta.
Sob sobrecarga um sistema tem três opções: desacelerar o producer, descartar com um contador, ou perder em silêncio. Só a terceira é inaceitável, e ela é o comportamento padrão de um código a quem nunca se fez a pergunta. Perda no pico é uma fila que cresceu até a memória acabar, ou uma confirmação emitida antes da durabilidade.
Um descarte com um contador rotulado é uma quantidade conhecida que pode ser reconciliada depois. Um descarte sem contador não é dado perdido, é um número perdido.
A orientação de implementação do OpenRTB diz isso diretamente: a sequência que vai da requisição de anúncio, passando pelo leilão, até a renderização e a cobrança é fundamentalmente não transacional. Há partes demais entre as duas contagens.
O atraso é esperado, não excepcional. A bid request pode carregar uma expiração de impressão e o lance, o atraso que o bidder tolera, e a mesma orientação dá regras de bolso que vão da ordem de um minuto para web a muito mais para formatos in-app cacheados e vídeo com stitching.
Nenhum dos dois campos é um contrato. A orientação diz claramente que uma notificação de cobrança que chega depois da expiração declarada pelo bidder ainda pode ser faturável - uma discussão de política entre bidder e exchange, e não algo que o protocolo imponha.
Um evento que chega depois da janela não é um defeito do pipeline, é uma propriedade do meio. A única escolha real é se o número se move em público enquanto a janela está aberta, ou se move em privado depois.
Os identificadores que a exchange substitui nas URLs de notificação e de tracking são o identificador de leilão vindo da bid request, o identificador de impressão e, quando o bidder emitiu um, o identificador de lance. Nenhum dos três é uma chave sozinho.
A especificação chama o identificador de leilão de único por exchange, não globalmente único: duas exchanges podem te entregar a mesma string no mesmo dia. O identificador de impressão é único apenas dentro da própria bid request, muitas vezes literalmente 1. O identificador de lance é opcional.
A chave que se sustenta é a composta: a exchange ou o seat pelo qual você transacionou, mais o identificador de leilão, mais o identificador de impressão. Gere-a do lado do bidder no momento do leilão, e trate qualquer coisa mais curta como prefixo, não como chave.
Se essas macros estiverem ausentes dos beacons, a reconciliação em nível de evento é impossível, e o que resta é casar por horário, placement e criativo. O que dá para construir no lugar é uma ponte de seis contagens, cada uma nomeando sua razão para diferir da etapa acima.
Uma razão estável entre as etapas é o objetivo e um movimento inexplicado é o alarme. Dentro de um mesmo sistema, as razões entre saltos devem ficar em um, e qualquer desvio é o sinal. Na fronteira entre leilão e medição, um é a leitura suspeita.
Os mesmos contadores, lidos como razões, transformam a pergunta em aritmética: aceitos sobre enviados, produzidos sobre aceitos, consumidos sobre produzidos, inseridos sobre consumidos. Quatro razões em um gráfico dizem para onde os eventos foram antes de alguém abrir um log. Acrescente um número de sequência do lado do producer por fonte e por partição, e um buraco vira evidência em vez de suspeita.
Uma pergunta que a ponte não responde e um contrato responde: sobre qual desses números você paga. O vendedor contabiliza receita pelo seu próprio evento faturável, o comprador faz o pacing pelo dele, e a orientação trata uma diferença persistente como uma conversa de suporte entre as partes.
Decida com antecedência qual contagem é o sistema de registro do gasto, e a partir de que diferença uma nota no relatório vira um chamado com a exchange. O trabalho acima compra atribuição da perda, duplicatas honestas e uma reconciliação explicada linha por linha. Ele não compra o que vem a seguir.
Um pipeline que consegue responder a essas perguntas de divulgação tem uma história de integridade. Um que não consegue tem uma opinião, e é sobre opinião que se discute no fim de um trimestre.
A falha contra a qual vale projetar não é a hora faltante que abre uma investigação. É a versão silenciosa: uma costura que descarta sem contador, um insert confirmado antes de ser durável, e uma reconciliação sobre uma janela ainda aberta.
O que a amBrain pode sustentar publicamente: a amBrain é uma empresa de engenharia de software de Yerevan, Armênia, que constrói plataformas de trading de baixa latência, matching engines e sistemas de real-time bidding em Rust. A amBrain constrói software desde 2019. Reconstruir um pipeline de medição não é um trabalho descrito aqui. Se os números param de reconciliar do lado do bidder e da exchange - os próprios registros de lance, vitória e impressão - essa é a conversa que vale ter, e ela começa pela curva de estabilização, não por uma reconstrução.
Traga sua arquitetura atual e o modo de falha que preocupa você, e vamos analisá-lo juntos em meia hora.