Em um sistema de pagamentos, publicar um evento "pagamento aprovado" e enfileirar um job "enviar e-mail" parecem a mesma ação. Não são. Pub/Sub vs message queue separa dois modelos mentais distintos, e trocar um pelo outro muda quem depende de quem na sua arquitetura.
Pub/Sub vs message queue: qual é a diferença real?
Pub/Sub vs message queue é a diferença entre anunciar um fato que já aconteceu e enfileirar um trabalho que alguém precisa executar. No pub/sub, o produtor publica um evento e não sabe quem vai consumir; na fila, o produtor depende de um worker para tirar aquele item da fila.
O modelo mental do pub/sub é o do YouTube: o canal publica um vídeo e quem está inscrito decide assistir ou não. O pagamento aprovado é publicado como evento, e os sistemas de estoque, entrega e analytics reagem de forma independente, sem que o serviço de pagamentos saiba que eles existem. Em JSON, esse evento costuma ser algo como {"type": "payment_succeeded", "id": 123}: um fato registrado, com identificador próprio, jogado no ar.
Na fila de mensagens o raciocínio muda. Você publica "comprimir esta imagem" e espera que algum worker pegue o job e o execute. A imagem não pode ser comprimida três vezes por três workers diferentes: cada mensagem deve ser processada uma vez, mesmo que existam cem workers escutando a mesma fila. Nada impede, porém, que várias filas recebam a mesma carga ou que cada job carregue metadados como o URL da imagem e o nome do arquivo.
Essa inversão de dependência é o ponto central. No pub/sub quem depende é o consumidor do evento; na fila quem depende é o produtor, que precisa que o trabalho seja concluído. Muitos sistemas usam os dois padrões juntos, cada um no trecho em que faz sentido.
Evento, comando e o acoplamento entre serviços
A escolha entre evento e comando define o acoplamento da arquitetura. Em um sistema de pagamentos, publicar payment_succeeded é anunciar um fato; enviar uma ordem direta ao serviço de entregas seria um comando, e isso cria um vínculo entre os dois serviços.
Um evento pode ter zero, um ou vários assinantes, e o produtor segue funcionando em todos os casos. Um comando tem destinatário definido e espera execução. Essa distinção importa mais do que a ferramenta escolhida, porque ela determina o que quebra quando um serviço sai do ar.
Na prática, os dois padrões convivem. O serviço de e-mail assina o evento de pagamento aprovado e, ao recebê-lo, enfileira um job de envio. A fila garante que o e-mail seja enviado pelo menos uma vez, enquanto o evento apenas informa que o pagamento aconteceu.
Modelos de entrega: at-least-once, at-most-once e exactly-once
O modelo de entrega é uma decisão separada do padrão de mensageria. O at-least-once pode entregar a mesma mensagem mais de uma vez, o at-most-once pode perdê-la e o exactly-once tenta garantir entrega única, com custo e complexidade maiores.
Kafka e o Amazon SQS, serviço de filas gerenciado da AWS, operam com semânticas diferentes. Confundir o padrão de entrega com a garantia de processamento único é uma fonte comum de bugs em produção.
Na prática, você quase sempre projeta para at-least-once e torna o consumidor idempotente. Enviar o mesmo e-mail duas vezes é um problema visível; comprimir a mesma imagem duas vezes costuma ser apenas desperdício de CPU, o que explica por que a idempotência virou requisito padrão em filas.
Quando usar cada padrão na prática
Você usa pub/sub quando precisa notificar vários interessados sobre um fato e não quer que o produtor conheça os consumidores. Você usa fila quando precisa distribuir unidades de trabalho entre workers e garantir que cada job seja executado uma vez.
A comparação abaixo resume as dimensões que mais pesam na decisão técnica.
| Dimensão | Pub/Sub | Message queue |
|---|---|---|
| O que a mensagem representa | Um fato que aconteceu | Um trabalho a executar |
| Quem depende de quem | O consumidor depende do evento | O produtor depende do worker |
| Número de consumidores | Vários, cada um com sua cópia | Um worker por mensagem |
| Efeito de um worker fora do ar | Nenhum para o produtor | Job espera na fila |
| Justificativa para idempotência | Menos crítica | Quase sempre obrigatória |
| Cobrança típica | Por mensagem publicada e entregue | Por requisição e volume de dados |
Um erro frequente é tratar pub/sub como fila com vários consumidores. Se três serviços assinam o mesmo evento, cada um recebe sua própria cópia; se três workers escutam a mesma fila, cada mensagem vai para apenas um deles. São comportamentos opostos.
Vale checar também o custo operacional. Filas gerenciadas cobram por requisição e volume de dados, e sistemas de pub/sub cobram por mensagem publicada e entregue. A conta muda bastante conforme o volume, então esse é um dado a confirmar na documentação atual do provedor escolhido.
Exemplo de fila com RabbitMQ e Bun
Uma fila de mensagens pode rodar inteira na sua máquina, sem infraestrutura dedicada. A demonstração do canal usa Bun, runtime de JavaScript, um container RabbitMQ e dois processos: um produtor que enfileira jobs e um worker que consome.
O produtor adiciona um job de envio de e-mail na fila a cada 1 segundo, e o worker lê esses jobs em outro processo a cada 500 ms. Os dois não compartilham funções nem memória: conversam apenas pela fila, o que permite subir e derrubar o worker sem perder os jobs já enfileirados.
O roteiro da demonstração funciona assim:
- Subir o broker em Docker, no mesmo host e porta que o produtor e o worker vão usar.
- Iniciar o produtor com
bun run producere observar os jobs entrando na fila. - Iniciar o worker com
bun run workere ver os jobs sendo consumidos, um a cada meio segundo. - Derrubar o worker no meio do caminho e conferir que os jobs continuam na fila, esperando.
- Subir o produtor de novo e ver os jobs 84 e 85 entrarem na sequência em que o consumo parou.
Na transcrição do vídeo, a biblioteca citada como "Bull MQ" e o "Redges" foram mencionados de forma ambígua. O BullMQ é uma biblioteca de filas para Node.js baseada em Redis, e é esse o par que aparece no exemplo de código. O worker do exemplo só escreve um log dizendo que o e-mail foi enviado, mas ali caberia qualquer chamada externa, como uma API de envio real.
O padrão producer e worker é o mesmo em qualquer stack. Você troca Redis, RabbitMQ ou SQS pelo serviço de filas da sua preferência, mas o desenho continua: alguém enfileira, alguém consome, e a fila absorve a diferença de ritmo entre os dois.
Erros comuns ao migrar de pub/sub para fila
O erro mais comum é assumir que trocar pub/sub por fila é uma substituição direta. Não é. Você precisa rever quem depende de quem, o modelo de entrega e o que acontece quando a mensagem é processada duas vezes.
Outro problema é esquecer que cada assinante de um tópico recebe sua própria cópia da mensagem. Em um serviço de estoque e outro de entrega, ambos precisam reagir ao mesmo pagamento, e a fila não entrega esse comportamento sem configuração adicional.
Também é frequente subestimar o trabalho operacional. Filas precisam de retry, dead letter queue e monitoramento de profundidade, e nenhum desses itens vem de graça. A simplicidade do exemplo local não se traduz automaticamente em produção sem esses controles.
Do exemplo local ao ambiente de produção
O exemplo local roda com RabbitMQ em Docker, um produtor e um worker na mesma máquina, e isso já mostra o essencial. Em produção, os três componentes costumam ficar separados: o serviço, o sistema de filas e os workers.
Vale separar as camadas com precisão. O Redis é o armazenamento que sustenta o BullMQ; o RabbitMQ é um broker de mensagens com implementação própria; e o SQS é um serviço gerenciado da AWS. Cada um tem modelo de operação e limites diferentes.
Nesse desenho, o serviço pode ser uma VPS, e os workers podem ser outras VPS ou funções sob demanda. Quando a fila cresce, você sobe mais workers; quando o volume cai, você derruba. O desenho sacrifica acoplamento em troca de flexibilidade de escala.
Vale lembrar que o vídeo é de junho de 2026 e usa um exemplo simplificado, próximo do quickstart da documentação do BullMQ. Antes de reproduzir o código em produção, confira na documentação oficial a versão atual do BullMQ, do Redis e do runtime que você escolher adotar.
FAQ sobre pub/sub e message queue
Pub/Sub é a mesma coisa que message queue?
Não. Pub/Sub publica um fato para vários assinantes interessados, enquanto a fila publica trabalho para ser retirado e executado por um worker. No pub/sub o produtor não depende de ninguém; na fila, o produtor depende de quem consome.
Um evento pode ter vários consumidores?
Sim, e cada assinante recebe sua própria cópia da mensagem. Isso é útil quando vários sistemas precisam reagir ao mesmo fato, mas exige cuidado com idempotência em cada consumidor.
Posso usar os dois padrões no mesmo sistema?
Pode, e é comum. O serviço assina um evento de pagamento aprovado e, em seguida, enfileira o envio de e-mail para que um worker execute o trabalho sem bloquear o fluxo principal.
Qual modelo de entrega devo escolher?
O at-least-once é o mais prático no dia a dia, desde que o consumidor seja idempotente. O exactly-once custa mais e raramente compensa quando a operação pode ser repetida sem efeito colateral.
Preciso de infraestrutura dedicada para começar?
Não. Você roda um broker como o RabbitMQ em Docker na própria máquina e sobe produtor e worker em processos separados para entender o fluxo antes de ir para a nuvem.
O que é o RabbitMQ?
É um broker de mensagens open source que serve como intermediário entre produtores e consumidores. Ele mantém a fila funcionando mesmo quando o worker está fora do ar por algum tempo.
O que é o BullMQ?
É uma biblioteca de filas para Node.js construída sobre o Redis. Ela permite criar filas, adicionar jobs e registrar workers que processam esses jobs conforme a capacidade disponível.
Qual a diferença entre Redis e RabbitMQ?
O Redis é um armazenamento em memória usado como base para filas como o BullMQ; o RabbitMQ é um broker com protocolo próprio, voltado para roteamento de mensagens entre serviços.
Vale a pena estudar pub/sub e filas para entrevistas de arquitetura?
Vale, porque a diferença entre evento e comando aparece com frequência em perguntas de system design. Quem entende o modelo mental antes da ferramenta consegue justificar a escolha em vez de apenas citar nomes de serviços.
Onde isso vira curso?
O vídeo faz parte do conteúdo do canal e do Crazystack, plataforma de cursos de tecnologia. O curso de system design cobre bancos de dados, filas, load balancer, autenticação, DNS, CDN, deploy, escalabilidade e o design de uma aplicação como o WhatsApp.
Onde aprofundar esses conceitos
Filas e eventos aparecem em entrevistas de arquitetura com frequência, e a diferença entre eles costuma separar respostas genéricas de respostas bem fundamentadas. Entender o modelo mental antes da ferramenta evita decorar nomes de serviços sem saber quando aplicar cada um.
Antes de partir para a ferramenta, defina o que a mensagem representa. Se ela informa algo que aconteceu, o caminho é o pub/sub. Se ela pede que alguém execute uma tarefa, o caminho é a fila. Essa pergunta resolve a maior parte das dúvidas de arquitetura.
Ferramentas como o Crazystack Typescript organizam esse tipo de estudo em trilhas, e o Bootcamp do Dev Doido é outro caminho para quem quer estruturar a base. Gustavo Dev Doido e outros profissionais do canal mantêm conteúdo gratuito sobre o tema no YouTube.
Conteúdo de referência ajuda, mas o entendimento vem da prática. Suba um broker local, escreva um produtor e um worker, force um erro no meio do processamento e observe o que acontece com a fila. Em poucas horas você entende mais do que em semanas de leitura.
CTA
Se você tem uma explicação sobre filas, eventos ou arquitetura gravada em vídeo, esse conhecimento pode virar texto. O Skala Blog converte a transcrição de um vídeo do YouTube em um artigo estruturado, pronto para revisão.
Basta visitar Skala Blog, colar a URL do vídeo, gerar a transcrição e produzir o artigo a partir dela. O vídeo que você já gravou continua trabalhando por você em outro formato, sem regravar nada.
Fork this article
Start a new branch from the same video, shaped your way. You keep the credit; the original keeps the attribution.
A fork in another language is filed as a translation of this article, so the two pages point at each other. You can unlink it later from the editor.
0/240
You are creating
- Format
- For
- Language
- Source
- Your angle
You will be asked to sign in before it is generated.
Buy credits