Case: chat / messaging (WhatsApp-like)
- ⬜🚦 Case: distributed rate limiter(System Design Interview Prep)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
O engano de começar pela conexão
Perguntado sobre um sistema de mensagens, quase todo candidato começa por conexão persistente. Não está errado — está incompleto, e da forma que mais custa pontos: transporte é a parte fácil. O problema real aparece quando o destinatário está com o telefone desligado.
Uma mensagem enviada para quem está offline precisa ser guardada, entregue quando a pessoa voltar, confirmada, e não pode duplicar se a confirmação se perder. Isso é armazenamento durável, ordenação e semântica de entrega — nenhum dos três é resolvido pelo protocolo de conexão.
O teste de uma resposta completa
Pergunte a si mesmo: o que acontece se o destinatário só abrir o aplicativo daqui a três dias? Se a resposta envolve apenas a conexão, metade do sistema ainda não foi projetada.
Onde cada peça vive
- → envia
- → grava primeiro
- → está online?
- → sim: qual servidor
- → não: enfileira
- → entrega direta
- → confirma
- Fora da AWS
- Rede e entrega
- Banco de dados
- Compute
- Integração de apps
Repare que o armazenamento aparece antes de qualquer entrega, e que a notificação não carrega a mensagem — só acorda o aplicativo. Quem desenha a entrega direta como caminho principal e o offline como "detalhe" inverteu a importância: o caminho offline é o que define o sistema.
- 1 · O identificador nasce no cliente. É o que torna o reenvio seguro: se a rede cair depois de o servidor gravar mas antes de a confirmação voltar, o app reenvia com o MESMO identificador e o servidor reconhece a repetição em vez de duplicar.
- 2 · Gravar antes de entregar. A ordem importa. Entregar primeiro e gravar depois perde a mensagem se o serviço morrer no meio — e o remetente já viu o sinal de enviado.
- 3 · A sequência vem do servidor. Relógio de celular diverge, e usuário pode alterá-lo. Um contador por conversa, atribuído pelo servidor, é o que garante que os dois lados vejam a mesma ordem.
- 4 · Presença decide a rota. Com milhões de conexões abertas espalhadas por muitos servidores, é preciso saber em qual deles o destinatário está. Esse registro é o componente mais esquecido do desenho — e o mais consultado.
- 5 · Offline vira fila e notificação. A mensagem já está gravada; a fila só coordena a tentativa. A notificação existe para acordar o aplicativo fechado — ela avisa, não transporta o conteúdo.
- 6 · A confirmação fecha o ciclo. Sem ela não há "entregue" nem "lido", e não há como saber que se pode parar de tentar. É a confirmação, não o envio, que encerra a operação.
Semântica de entrega: por que "exatamente uma vez" não existe
A rede pode perder qualquer mensagem, inclusive a confirmação. Isso deixa apenas duas opções honestas, e a escolha entre elas é a decisão de projeto:
| Garantia | O que significa | Preço |
|---|---|---|
| No máximo uma vez | Envia e não repete. Se a confirmação se perde, a mensagem se perde | Inaceitável num chat: mensagem sumida é o pior defeito possível |
| Pelo menos uma vez | Repete até receber confirmação. Se a confirmação se perde, a mensagem chega duas vezes | Duplicata — resolvida pelo identificador gerado no cliente |
| Exatamente uma vez | Não existe de verdade em sistema distribuído. O que existe é repetir e descartar duplicata pelo identificador | É o "pelo menos uma vez" com deduplicação — e vale dizer isso com todas as letras na entrevista |
A resposta que impressiona
"Uso pelo menos uma vez com identificador gerado no cliente e deduplicação no servidor. Isso me dá exatamente uma vez do ponto de vista do usuário, que é o que importa — a garantia real do transporte continua sendo repetição."
Por que a entrega de mensagens exige mais que uma conexão bidirecional?
O que escala mal: conexões, não mensagens
Mensagem é barata: texto curto, poucos quilobytes. O que custa é manter milhões de conexões abertas, cada uma consumindo memória e um descritor de arquivo, mesmo ociosa. Um usuário que não troca mensagem nenhuma durante horas continua custando.
- Registro de presença vira o componente mais consultado do sistema: toda mensagem pergunta "onde está o destinatário?". Costuma ficar em armazenamento em memória, com expiração — presença é dado que envelhece sozinho.
- Conexões precisam de balanceamento com afinidade: o destinatário tem de ser alcançável no servidor onde está conectado, ou os servidores precisam conversar entre si.
- Grupo grande é o problema de contas muito seguidas outra vez: uma mensagem num grupo de dez mil pessoas é uma escrita e dez mil entregas.
- Cifragem ponta a ponta muda o projeto do servidor: sem poder ler o conteúdo, não há busca no servidor, nem pré-visualização, nem moderação automática. É decisão de produto antes de ser de engenharia.
O trade-off da cifragem ponta a ponta que raramente se menciona
Ela também impede o servidor de gerar a pré-visualização em notificação. É por isso que aplicativos cifrados mostram "Nova mensagem" em vez do texto quando o aparelho está bloqueado — não é escolha de interface, é consequência de o servidor genuinamente não saber o que foi dito.
Perguntas frequentes
❓ Como garantir entrega de mensagem em chat?
❓ Como escalar conexões persistentes?
❓ Como armazenar histórico de conversa?
Fixando
Como garantir a ordem das mensagens numa conversa?
Qual é o desafio de escala específico do modelo de conexões persistentes?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…