Comunicação entre sistemas: o que você realmente precisa saber
A maioria dos desenvolvedores começa achando que comunicar serviços é coisa simples. Você chama uma URL, recebe um JSON, ponto. A realidade é bem mais chata. Dependendo do cenário, você vai escolher entre métodos que têm trade-offs reais e muitas vezes ninguém te avisa sobre isso antes do projeto estourar. Vamos direto. Quais são os tipos de comunicação que aparecem no dia a dia de quem constrói software distribuído.
Quais são os tipos de comunicação mais usados na prática
HTTP/REST continua sendo o mais comum. É simples, todo mundo entende, tem ferramenta pra tudo. Mas tem um detalhe que gente nova quase sempre perde: HTTP é síncrono por natureza. Se o serviço B demora três segundos, seu cliente fica travado nesses três segundos. Isso parece óbvio até acontecer em produção numa sexta à noite. gRPC nasceu dentro do Google e ganhou popularidade por bom motivo. Usa Protocol Buffers, é binário, e costuma ser de três a dez vezes mais rápido que JSON sobre HTTP em cenários de muita chamada interna. O problema é a curva de aprendizado. Seu time precisa lidar com .proto files, geração de código, e debugging de payloads binários não é tão simples quanto abrir um response no browser.
Mensageria assíncrona — Kafka, RabbitMQ, SQS — é quando você para de esperar resposta e simplesmente empurra uma mensagem pro meio e segue a vida. Isso resolve o problema da cascata de timeouts, mas introduz complexidade nova: ordenação, retry, dead letter queues, exatamente-once vs at-least-once delivery. Eu levei seis meses pra parar de perder mensagens num RabbitMQ porque na época eu não configurava ACK corretamente. Perdi dados de pagamento. Ninguém esquece essa lição. WebSockets são úteis quando você precisa de comunicação bidirecional em tempo real. Chat, dashboards ao vivo, jogos. Mas cuidado: manter conexões abertas consome memória no servidor e exige cuidado com scaling. Um load balancer qualquer não lida bem com WebSocket sem config específica de upgrade de conexão. Já vi pipeline inteiro cair porque o balanceador reiniciava conexões a cada dois minutos.
GraphQL não é exatamente um protocolo de comunicação, mas mudou a forma como frontend e backend conversam. A vantagem é clara: evita over-fetching e under-fetching. A desvantagem prática é que queries aninhadas mal feitas viram N+1 queries no banco de dados. O DataLoader ajuda, mas se seu time não tiver disciplina, o GraphQL vai mascarar problemas de performance que REST expondo imediatamente. gRPC-Web e HTTP/2 merecem menção separada. HTTP/2 permite multiplexação — várias requisições numa única conexão TCP — o que elimina grande parte da dor do HEAD-of-line blocking que atormentava HTTP/1.1. gRPC-Web é basicamente gRPC adaptado pra rodar no browser, que não suporta HTTP/2 nativamente da forma que precisa.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Pegadinhas que ninguém conta em tutorial
Primeiro: latência não some. Mesmo que você troque REST por gRPC, se seus serviços estão em regiões diferentes, a luz viaja na fibra e isso limita seu throughput. Já configurei um benchmark que parecia milagre com gRPC e depois descubri que 70% do tempo era de rede, não de serialização. O ganho real foi perto de zero. Segundo: versionamento é obrigatório desde o dia um. Esqueça a ideia de que você vai consertar isso depois. Tenho visto gente com API REST que mudou um campo sem versão e quebraram três integrações de parceiros internos. Com gRPC, o Protocol Buffers tem compatibilidade hacia frente e para trás se você seguir as regras, mas se quiser usar campos deprecated ou mudar numeração de enums, precisa de estratégia. Eu uso namespace protobuf por ambiente — dev, staging, prod — e never muto números de campo em produção.
Terceiro: o tipo de comunicação que você escolhe dita o padrão de retry. Chamada síncrona permite retry imediato com backoff exponencial. Mensageria assíncrona exige policy de DLQ + monitoramento visual. Sem DLQ configurada, mensagens mortas somem e seu relatório de erro vai mentir pra você. Um case específico meu: num microserviço de notificação que usava filas SQS, o problema era que mensagens com payload muito grande travavam o consumer. O SQS tem limite de 256KB por mensagem. Minha equipe colocou payloads de até 2MB achando que ia funcionar. Na prática, as mensagens ficavam penduradas no invisível queue e o consumer processava outras menores, criando um congestionamento. A solução foi simples: chunkear o payload antes de enfileirar e montar no consumer. Gastou duas semanas a mais no sprint, mas resolveu.
Quando cada tipo falha completamente
REST não escala bem se você precisa de centenas de chamadas por segundo entre serviços internos. Cada handshake TCP + parsing de JSON gasta ciclos desnecessários. Nesse cenário, gRPC ou mensageria binária saem na frente. Kafka não é solução mágica para tudo. Se você precisa de consistência forte e latência sub-milissegundo, Kafka vai te decepcionar. Ele é escrito pra throughput alto com tolerância a atrasos. Eventual consistency é o preço. Se seu domínio exige transações ACID entre serviços, talvez você precise de SAGA com compensação ou até repensar a decomposição.
WebSockets falham miseravelmente em ambientes com firewall agressivo ou proxy que não respeita o protocolo de upgrade. Infraestrutura corporativa velha ainda mata conexão WebSocket sem aviso. Se sua aplicação vai rodar dentro de grandes empresas, teste isso cedo. O conselho mais honesto que eu posso dar: comece simples. HTTP REST com OpenAPI bem documentado. Só migre pra algo mais complexo quando o problema justificar. A maioria dos times não chega lá. Eles escolhem Kafka no dia um porque viu no LinkedIn e agora precisam de um engenheiro dedicado pra manutenção da fila. Não faça isso.
A escolha certa depende de três variáveis: latência esperada, volume de mensagens, e tolerância a inconsistência temporária. Anote esses três valores antes de decidir qualquer coisa. O resto é implementação.