Último texto da série em que eu leio arquiteturas conhecidas a partir de material público de engenharia. Não é a planta: é a leitura do que organiza o resto.
E esse fecha bem, porque a contribuição do LinkedIn não foi um produto: foi uma abstração que hoje está em quase toda empresa de tecnologia.
O problema que quase toda empresa tem
Você tem um sistema de perfis. Depois um de busca, que precisa dos dados do perfil. Depois um de recomendação, que também precisa. Depois um data warehouse, um sistema de e-mail, um de notificação, um de antifraude.
Cada um precisa de uma cópia atualizada de dados que vivem em outro lugar. E cada integração é construída sozinha: um job noturno aqui, uma chamada de API ali, um gatilho de banco acolá, um consumidor de fila específico.
Com dez sistemas, isso vira uma teia que ninguém consegue desenhar num quadro. Cada mudança de esquema quebra três integrações que ninguém lembrava que existiam.
A ideia que saiu do LinkedIn e virou Kafka é enganosamente simples: em vez de cada sistema falar com cada sistema, todo mundo publica num log ordenado e todo mundo lê dele.
Por que o log é a abstração certa
Eu demorei pra entender por que isso é mais que uma fila com outro nome. A diferença está em três propriedades.
Ordem. O log tem sequência. Cada consumidor sabe exatamente onde parou, e esse marcador é dele, não do produtor. Dois consumidores no mesmo fluxo, em velocidades diferentes, não interferem um no outro.
Retenção. A mensagem não some ao ser consumida. Ela fica pelo período configurado. Isso permite uma coisa que fila tradicional não permite: reprocessar. Um consumidor novo lê o log inteiro desde o começo e reconstrói o estado dele.
Essa é a propriedade que muda o custo de errar. Bug no cálculo do índice de busca? Corrige o código, volta o marcador, reprocessa. Sem exportação, sem migração, sem script de backfill.
Desacoplamento real. O produtor não sabe quem consome. Adicionar o oitavo consumidor não exige mudar nada nos produtores. Em integração ponto a ponto, cada consumidor novo é uma negociação.
É a mesma ideia que descrevi em log append-only, levada ao nível da empresa inteira em vez do nível da tabela.
Captura de mudança: o log sem pedir licença
Tem um detalhe operacional que decide se isso funciona na prática.
Pedir para todos os times publicarem eventos é uma migração organizacional demorada. E dupla escrita, gravar no banco e publicar no log, é a receita de inconsistência que eu descrevi em outbox pattern: as duas operações podem falhar separadamente.
A saída é ler o próprio log de transação do banco e transformar cada mudança em evento. O sistema de origem não muda nada, não sabe que está sendo observado, e o fluxo fica garantidamente consistente com o que foi commitado.
Isso é o que hoje se chama captura de dados de mudança, e é a peça que torna a adoção viável sem reescrever tudo.
Os graus de separação
O outro problema interessante desse produto é de grafo, não de log.
Quando você vê um perfil, o sistema diz se a pessoa é conexão de primeiro, segundo ou terceiro grau. Isso parece um detalhe de interface e é uma consulta cara.
Segundo grau é a união das conexões de todas as suas conexões. Alguém com 500 conexões que também têm 500 cada tem, em ordem de grandeza, centenas de milhares de perfis de segundo grau. Terceiro grau explode pra dezenas de milhões.
Fazer isso com junção em banco relacional, em tempo de requisição, para cada visita de perfil, não fecha.
O que se faz é um serviço dedicado, com o grafo em memória, particionado, respondendo consultas de distância limitada com estruturas específicas pra isso. E, para o caso mais frequente, o resultado é pré-calculado e cacheado.
O padrão aqui é o mesmo que apareceu em toda a série: quando a consulta é cara e frequente, ela vira um sistema próprio. Não uma query melhor, não um índice novo: um serviço com estrutura de dados desenhada pra aquela pergunta.
O feed, com um problema a mais
O feed enfrenta o mesmo dilema de fan-out que descrevi no Twitter, com um agravante: aqui o conteúdo relevante não é só de quem você segue. Ele vem de conexões de segundo grau, de empresas, de grupos e de anúncios.
Isso amplia demais o conjunto de candidatos e reforça a estrutura de funil que descrevi no YouTube: gerar candidatos barato, pontuar caro.
Fico com a impressão de que, nos seis textos, essa foi a estrutura mais recorrente. Reduzir antes de decidir aparece em todos.
O que eu levo pra sistema pequeno
Um log central resolve integração antes de você ter dez sistemas. Não precisa de Kafka. Uma tabela de eventos com marcador por consumidor já dá ordem, retenção e desacoplamento. O ganho aparece no terceiro consumidor.
Poder reprocessar muda o custo de errar. Se corrigir um bug de cálculo significa voltar o marcador e reler, o medo de mexer some. Sem isso, cada erro vira um script de correção escrito sob pressão.
Não peça a todos os times que publiquem eventos. Leia a mudança na origem. A adoção é o problema difícil, não a tecnologia.
Consulta cara e frequente merece um sistema próprio. Quando otimizar a query já não resolve, a resposta costuma ser uma estrutura de dados diferente, mantida por fora, alimentada pelo log.
Fecho a série com a impressão que ficou mais forte: nenhum desses sistemas é admirável pela tecnologia que usa. Eles são admiráveis por uma decisão tomada cedo, quase sempre sobre onde o trabalho acontece — antes ou depois, no cliente ou no servidor, na escrita ou na leitura. O resto é consequência.
Os seis textos, com os diagramas, também estão reunidos num PDF.