Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

01 - At-most-once

#at-most-once#fire-and-forget#perda-mensagens#performance#telemetria
video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

At-most-once

At-most-once é a garantia de entrega mais fraca da mensageria: cada mensagem é enviada no máximo uma vez, e a perda é considerada aceitável. Não existe confirmação de processamento, não existe reentrega em caso de falha e não existe deduplicação, porque nada volta. O padrão é frequentemente caricaturado como descuido, mas em produção é uma escolha deliberada com base econômica: para uma classe enorme de dados, perder um pequeno percentual custa menos que pagar a latência, a complexidade e a infraestrutura da garantia forte. Métricas, logs, telemetria, rastreamento distribuído, sinalização de presença e notificações push de baixo valor vivem bem nessa semântica. Para o arquiteto, a competência central não é evitar at-most-once, é reconhecer com precisão em quais fluxos ele é suficiente e blindar os demais, evitando ao mesmo tempo o excesso de engenharia e a aplicação acidental da garantia fraca onde o negócio exige precisão.

Conceito e semântica formal

A semântica at-most-once promete no máximo uma entrega por mensagem, sem prometer ao menos uma. Entre enviar zero vezes, quando a rede falha ou o processo morre no meio do caminho, e enviar uma vez, qualquer resultado é aceitável pelo contrato. O que a garantia proíbe é a duplicata, e é exatamente essa proibição que a torna barata.

O custo baixo vem do que o padrão não precisa fazer. Sem ack, o produtor não espera confirmação e o broker não retém estado por mensagem; sem reentrega, não há buffer de redelivery; sem duplicata, o consumidor não precisa de idempotência nem deduplicação. Todo o caminho fica otimizado para throughput e latência, e é esse o pagamento que a perda eventual compra.

Na outra ponta, at-least-once promete ao menos uma entrega e aceita duplicatas; exactly-once promete uma única entrega efetiva, ao preço de mecanismos de transação e deduplicação. As três semânticas formam uma escada de custo, e at-most-once é o primeiro degrau de propósito.

O nome descreve o contrato com precisão matemática: no máximo uma vez. A formulação vem da taxonomia clássica de semânticas de entrega de sistemas distribuídos, e a precisão importa porque o contrato exclui a duplicata por construção. Em fluxos onde duplicar é pior que perder, a semântica fraca é paradoxalmente a mais segura.

O problema que resolve

O problema direto é o custo da certeza. Confirmar cada mensagem custa uma viagem de volta, reter a mensagem até o ack custa estado no broker e processar duplicatas custa lógica no consumidor. Em fluxos de milhões de eventos por minuto, multiplicar esse custo por dado que não exige precisão é desperdício puro.

O segundo problema é a desacoplagem em situações em que o emissor não pode esperar. Um serviço emitindo span de tracing dentro do caminho crítico de uma requisição não pode bloquear para confirmar entrega; o custo da telemetria não pode exceder o custo da operação observada. Fire and forget mantém o emissor livre, e a observabilidade deixa de ser imposto sobre a latência.

A conta fica clara com números. Uma requisição de cinquenta milissegundos com dez eventos telemétricos emitidos no caminho pagaria, com ack síncrono de um milissegundo cada, mais dez milissegundos de custo observacional, vinte por cento de sobrecarga. Com fire and forget em lote, o custo despenca para microssegundos de enfileiramento, e a aplicação mede-se com quase nenhum ruído.

O terceiro é a tolerância estatística. Para a maioria dos usos de telemetria, o valor está na tendência e na agregação, e não no dado individual. Perder 0,1% dos eventos de um painel de throughput não muda nenhuma decisão; garantir esses 0,1% pode dobrar o custo do pipeline.

Existe ainda o caso da perda irrecuperável por natureza. Um heartbeat que chegou atrasado não serve mais para nada; um evento de presença de três segundos atrás é obsoleto em qualquer tentativa de reentrega. Quando a mensagem perde o valor com o tempo, insistir na entrega é desperdício, e a semântica fraca é a única coerente com o conteúdo.

Funcionamento interno: o caminho sem ack

A implementação típica remove todos os pontos de espera do fluxo:

  1. O produtor coloca a mensagem em um buffer em memória e retorna imediatamente.
  2. Um mecanismo assíncrono, ou a biblioteca do broker, envia o buffer em lote pela rede.
  3. O broker aceita o que chegar e não exige confirmação de processamento do consumidor.
  4. Perdas em qualquer ponto, queda de rede, crash do produtor, fila cheia, são aceitas sem reentrega.

As decisões técnicas ficam nos detalhes do buffer e da fila cheia. Buffer em memória dá máxima velocidade e perde tudo em um crash do processo; buffer persistido dá mais segurança e devolve parte do custo. Fila cheia pode bloquear o produtor, o que trai o padrão, ou descartar o mais novo, o que é a escolha coerente com a semântica.

# Emissor de métricas: fire and forget deliberado
cliente = MetricClient(
    flush_interval_ms=1000,     # lote por segundo, não por evento
    max_buffer=10_000,          # limite de memória assumido
    on_overflow="drop_newest",  # fila cheia descarta, nunca bloqueia
)

def registrar_acesso(requisicao):
    cliente.increment(
        "http.requests",
        tags={"rota": requisicao.rota, "status": requisicao.status},
    )
    # sem await, sem retry, sem callback de falha
    # a perda de um ponto em buffer overflow é aceita pelo desenho

# No consumidor: nenhum mecanismo de idempotência necessário
def consumir(evento):
    agregador.acumula(evento)   # duplicata seria o único problema,
    # e a semântica at-most-once a exclui por construção

No lado do consumidor, a implementação coerente é o auto ack ou a ausência de confirmação: a mensagem é considerada processada ao ser entregue, e uma falha depois disso não gera nova entrega. É o auto acknowledge do RabbitMQ ou o consumo sem commit de offset garantido no Kafka; simples, rápido e, pela definição, displicente com a perda.

A escolha do transporte acompanha a semântica. UDP e protocolos de publicação sem confirmação casam naturalmente com o padrão em redes confiáveis de datacenter; TCP com fire and forget dá ordem e integridade de datagrama, sem a certeza de entrega. O que não combina com a semântica é o retry transparente da biblioteca: retries criam duplicatas, e duplicatas violam o contrato que era justamente o motivo da escolha.

Broker Configuração típica para a semântica
RabbitMQ Consumo com auto acknowledge e produtor sem confirm
SQS Envio e consumo sem deduplicação, sem política de retry
Kafka acks=0 ou 1 no produtor, commit de offset antes de processar
UDP direto Cliente de métricas padrão, como StatsD

Quando a garantia é suficiente em produção

A regra de decisão é econômica e gira em torno de duas perguntas: qual é o custo de perder uma mensagem, e qual é o custo de garantir que ela não se perca. A tabela resume os casos clássicos de cada lado.

A primeira pergunta exige resposta quantificada, e não intuitiva. Perder um evento de telemetria custa zero; perder um registro de cobrança custa dinheiro e credibilidade; perder uma notificação push custa, na pior hipótese, uma atualização atrasada. Classificar cada fluxo com essa régua, e registrar a classificação, é o que separa a decisão arquitetural da decisão por hábito.

Fluxo Perda aceitável? Justificativa Garantia adequada
Métricas de throughput e latência Sim Agregação tolera amostragem At-most-once
Spans de tracing distribuído Sim Amostragem já é parte do desenho At-most-once
Logs de acesso e depuração Quase sempre Volume alto, valor agregado At-most-once
Notificação push de conteúdo novo Em geral A próxima sincronização corrige At-most-once
Heartbeat e presença Sim O próximo tick substitui o anterior At-most-once
Cobrança, estoque, pagamento Não Cada evento é dinheiro At-least-once com idempotência
Comando de negócio auditável Não Reprocessabilidade exigida Log persistente, at-least-once

Telemetria é o território natural do padrão, e ferramentas do ecossistema assumem isso explicitamente. Exporters de métricas operam com UDP ou com filas de descarte, e sistemas de tracing amostram por desenho. A lição para o arquiteto é que a amostragem deliberada, com controle de taxa e de recorte, é superior à perda aleatória, porque preserva a representatividade estatística dos dados.

Há também os atenuadores úteis entre as garantias puras. Fire and forget com retry limitado, por exemplo, aceita perda no fim, mas tenta uma ou duas vezes o envio, reduzindo a taxa de perda sem custo de ack; é a configuração comum de clientes de métricas. O importante é manter a decisão explícita e medida, evitando que o atenuador escondido reintroduza duplicatas em fluxo que as exclui.

Comparação com as demais garantias

Aspecto At-most-once At-least-once Exactly-once
Falha antes da entrega Mensagem perdida Mensagem reentregue Entrega única garantida
Falha após a entrega Nada acontece Reentrega possível Deduplicação resolve
Duplicata no consumidor Impossível Possível e esperada Impossível
Custo de latência Mínimo Ack por mensagem Transações e marcação
Custo de implementação Trivial Idempotência no consumidor Transações e deduplicação
Caso típico Telemetria, presença Cobrança, integrações Pipelines fechados no broker

A leitura prática da tabela: at-most-once troca confiabilidade por velocidade, e essa troca é excelente quando o dado é estatístico e péssima quando o dado é transacional. A ambiguidade perigosa está no meio, em fluxos como notificação de usuário, onde a perda é tolerável, mas a duplicata incomoda; nesses casos, a solução costuma ser at-most-once com camada de aplicação suprimindo repetições na interface.

Um ponto de atenção é a fronteira entre pipelines: um fluxo pode ser at-most-once de ponta a ponta e ainda assim alimentar dados confiáveis, se o destino reconcilia com a fonte em janelas fechadas. Métricas agregadas por minuto em destino com retentativa por janela é o exemplo típico: a entrega individual foi fraca, e o resultado final é preciso o suficiente. O arquiteto avalia a garantia do sistema, e não a de cada elo isolado.

Erros comuns

  • Usar fire and forget por preguiça em fluxos de negócio: a garantia deliberada vira perda acidental, e a ausência de ack nunca foi discutida como decisão.
  • Aplicar at-most-once a dados que alimentam conciliação ou cobrança: a estatística não fecha, e o buraco aparece como divergência mensal.
  • Bloquear o produtor em fila cheia: o fluxo observado passa a depender da telemetria, invertendo a prioridade e contaminando a latência medida.
  • Perder buffer sem telemetria sobre a própria perda: o time não sabe quanto está descartando, e o dado deixa de ser estatisticamente confiável.
  • Assumir que UDP ou auto ack significa at-most-once sem revisar o caminho: retries escondidos na biblioteca reintroduzem duplicatas inesperadas.
  • Misturar fluxos fracos e fortes na mesma fila e no mesmo consumidor: a configuração comum acaba impondo o custo da garantia forte a todos os dados.
  • Tratar perda aceitável como perda invisível: sem taxa medida de descarte, ninguém percebe quando a perda saiu do esperado e virou incidente.

Boas práticas

  • Declare explicitamente a semântica de cada fluxo em documentação e em contrato, para que a perda assumida não seja surpresa para o consumidor.
  • Instrumente o próprio caminho fraco: métricas de descarte, buffer overflow e falha de envio transformam perda aceita em perda controlada.
  • Prefira amostragem com recorte a perda aleatória, garantindo representatividade dos agregados que alimentam decisão.
  • Mantenha o volume telemétrico fora do caminho crítico, com buffers e lotes, para que observabilidade nunca degrade a operação observada.
  • Revise a classificação dos fluxos a cada mudança de negócio, porque dado que era estatístico pode virar transacional, e a garantia precisa acompanhar.
  • Escolha em nível de arquitetura o transporte da telemetria, com capacidade de absorção verificada em teste de carga, para que descartes aconteçam por política e não por saturação.
  • Preserve a privacidade e o custo no desenho telemétrico: menos dados com amostragem bem definida frequentemente valem mais que o fluxo completo sem garantia.