MQTT vs NATS é uma comparação que surge quando uma equipe gosta da simplicidade do NATS para microsserviços e se pergunta se ele também pode atender seus dispositivos. Ambos são sistemas publish/subscribe leves, com assinaturas por wildcard e baixa latência, mas foram moldados por clients muito diferentes. Este guia compara suporte a dispositivos, garantias de entrega, persistência e ecossistema, e explica onde um broker MQTT gerenciado se encaixa ao lado do NATS.
Dois Sistemas Pub/Sub Leves
O MQTT é um protocolo padrão aberto da OASIS. Qualquer client compatível pode falar com qualquer broker compatível, e existem muitas implementações de ambos. Ele foi criado para telemetria de dispositivos com recursos limitados em redes pouco confiáveis, e é por isso que tem recursos como Last Will, retained messages e sessões persistentes.
O NATS é um sistema e protocolo de mensageria open source do ecossistema CNCF, com uma implementação de servidor principal. Ele foi criado para comunicação entre serviços cloud-native: requisição/resposta rápida, fan-out e distribuição de trabalho com balanceamento de carga dentro de data centers e entre eles. O core NATS é deliberadamente do tipo "dispare e esqueça"; o JetStream, embutido no servidor NATS, adiciona persistência, replay e garantias de entrega mais fortes.
Os dois são bons naquilo para que foram projetados. A questão é quais clients você está conectando.
MQTT vs NATS em Resumo
| Aspecto | MQTT | NATS |
|---|---|---|
| Natureza | Protocolo padrão OASIS, muitos brokers | Sistema open source, um servidor principal |
| Endereçamento | Topics com níveis /, wildcards + e # |
Subjects com tokens ., wildcards * e > |
| Entrega (core) | QoS 0, 1, 2 | No máximo uma vez no core NATS |
| Persistência | Último valor retido, filas de sessão | Streams JetStream com replay e retenção |
| Distribuição de trabalho | Shared subscriptions (MQTT 5) | Queue groups |
| Requisição/resposta | Response topic e correlation data (MQTT 5) | Embutido, com subjects de inbox |
| Presença | Keep alive e Last Will | Eventos de conexão via conta de sistema, sem Last Will |
| Último valor conhecido | Retained messages | Last-per-subject do JetStream ou KV store |
| Bibliotecas para dispositivos | Opções maduras para ESP32, Arduino, C embarcado, RTOS | Foco em linguagens de servidor; poucas opções para microcontroladores |
| Acesso pelo navegador | MQTT sobre WebSocket | NATS sobre WebSocket |
| Ecossistema industrial | Sparkplug B, Unified Namespace, suporte em PLCs e gateways | Limitado |
| Ambiente típico | Dispositivos, gateways, IHMs, dashboards | Microsserviços, backends edge-to-cloud, control planes |
O Suporte a Dispositivos É o Fator Decisivo
Em IoT, a diferença mais prática é a disponibilidade de clients. Existem clients MQTT para praticamente toda plataforma com que um engenheiro de dispositivos trabalha: bibliotecas para ESP32 e Arduino como a PubSubClient, bibliotecas em C embarcado para alvos RTOS, módulos celulares com MQTT no firmware do modem, PLCs e gateways industriais com MQTT embutido, e softwares de SCADA e historiadores que falam Sparkplug B. Sensores e gateways de prateleira muitas vezes já vêm com MQTT como opção de configuração.
Os clients NATS são excelentes para Go, Rust, Java, .NET, JavaScript, Python e C em hardware de classe Linux. Um Raspberry Pi ou um PC industrial roda esses clients com folga. Em microcontroladores e em firmware de fabricantes, o suporte a NATS é raro. Se você precisa que um dispositivo comercial envie dados sem escrever firmware, ele quase certamente falará MQTT, não NATS.
Garantias de Entrega e Persistência
O MQTT incorpora garantias de entrega em cada mensagem. Um dispositivo pode publicar um alarme com QoS 1 e uma leitura de vibração de alta frequência com QoS 0 na mesma conexão. Sessões persistentes guardam mensagens QoS 1 e 2 para um assinante que se desconecta, e retained messages guardam o último valor por topic para que um dashboard aberto depois veja o estado atual imediatamente. Para detalhes, veja os níveis de QoS do MQTT explicados e retained messages no MQTT.
O core NATS entrega para quem estiver conectado naquele momento e nada mais. Isso é rápido e simples, e é o modelo certo para muitas chamadas entre serviços. Quando você precisa de durabilidade, o JetStream armazena mensagens em streams com políticas de retenção, permite que consumidores confirmem e façam replay e pode deduplicar por ID de mensagem. O JetStream é mais capaz que as sessões MQTT para histórico e replay, mas é um conjunto separado de conceitos (streams, consumers, políticas de confirmação) que alguém precisa projetar e operar.
Presença e Estado dos Dispositivos
Sistemas IoT precisam responder o tempo todo: "este dispositivo está online e qual foi sua última leitura?" O MQTT responde às duas nativamente. Um dispositivo define um Last Will como offline em site1/pump7/status com a flag retain, publica online depois de conectar, e o broker publica o will se a conexão cair de forma abrupta. Veja o guia de Last Will and Testament no MQTT para o padrão completo.
No NATS, você normalmente construiria a presença com heartbeats de cada dispositivo ou observando eventos de conexão da conta de sistema do servidor, e guardaria os últimos valores em um bucket key-value do JetStream. Funciona, mas você está montando a solução em vez de apenas configurá-la.
Subjects vs Topics
Os modelos de nomenclatura são parecidos o suficiente para serem traduzidos. Um topic MQTT factory1/line2/cnc1/temperature corresponde naturalmente a um subject NATS factory1.line2.cnc1.temperature. O + do MQTT corresponde a um nível, como o * do NATS, e o # do MQTT corresponde ao restante, como o > do NATS. O servidor NATS chega a oferecer uma interface MQTT que mapeia topics para subjects dessa forma e aceita clients MQTT 3.1.1, o que é útil quando o NATS já é o backbone. Ela não suporta recursos do MQTT 5, então confira a documentação do NATS em relação aos recursos dos quais seus dispositivos dependem.
Uma Arquitetura Híbrida Prática
Muitas equipes usam os dois, cada um na camada a que se adapta:
- Dispositivos, gateways de PLC e IHMs se conectam a um broker MQTT via TLS.
- Um serviço de ponte assina os topics dos dispositivos e republica em subjects NATS para os microsserviços de backend.
- Os serviços usam requisição/resposta e queue groups do NATS internamente, e JetStream onde precisam de streams duráveis.
- Os comandos voltam pela ponte e são publicados no topic de comandos MQTT do dispositivo.
Uma ponte mínima de mão única em Go fica assim, usando o client Go do Eclipse Paho e o client oficial do NATS.
package main
import (
"crypto/tls"
"log"
"strings"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/nats-io/nats.go"
)
func main() {
nc, err := nats.Connect(nats.DefaultURL)
if err != nil {
log.Fatal(err)
}
defer nc.Drain()
opts := mqtt.NewClientOptions().
AddBroker("tls://broker.connectmq.com:8883").
SetClientID("YOUR_CLIENT_ID").
SetUsername("YOUR_USERNAME").
SetPassword("YOUR_PASSWORD").
SetTLSConfig(&tls.Config{MinVersion: tls.VersionTLS12}).
SetAutoReconnect(true)
opts.SetOnConnectHandler(func(c mqtt.Client) {
// Assine no handler de conexão para que a assinatura seja restaurada após reconexões
c.Subscribe("factory1/+/+/telemetry", 1, func(_ mqtt.Client, m mqtt.Message) {
subject := strings.ReplaceAll(m.Topic(), "/", ".")
if err := nc.Publish(subject, m.Payload()); err != nil {
log.Printf("nats publish failed: %v", err)
}
})
})
client := mqtt.NewClient(opts)
if token := client.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
log.Println("bridging MQTT to NATS")
select {}
}
O client Go do paho usa MQTT 3.1.1, que o ConnectMQ aceita junto com o MQTT 5. Para testar sem credenciais, use tcp://broker.connectmq.com:1883, qualquer client ID único e um prefixo de topic como connectmq/demo/<random-id>/ no servidor MQTT público (gratuito), pensado para testes. Fique atento a caracteres que são válidos em topics MQTT, mas especiais em subjects NATS, como . ou espaços, e trate-os na ponte.
Quando Escolher Cada Um
Escolha MQTT quando seus clients forem dispositivos, gateways, PLCs ou hardware de terceiros, quando a conectividade for instável ou quando você precisar de presença, estado retido e convenções industriais como Sparkplug B e um Unified Namespace.
Escolha NATS quando seus clients forem serviços que você escreve, rodando em redes confiáveis, e você quiser requisição/resposta rápida, queue groups e persistência opcional com JetStream com o mínimo de infraestrutura.
Escolha os dois quando tiver uma frota de dispositivos e um backend de microsserviços que já padronizou o uso de NATS.
Na camada de dispositivos, um broker MQTT gerenciado elimina o trabalho de operar e proteger um serviço exposto à internet. O ConnectMQ oferece MQTT 3.1.1 e 5.0, TLS, shared subscriptions no plano Serverless pago, cotas por plano e isolamento multi-tenant, sem uma ponte NATS embutida, então a ponte continua sendo um pequeno serviço seu, como mostrado. Se você também está comparando outros backends, veja MQTT vs Kafka e, para os fundamentos, o tutorial de MQTT.
Comece com o ConnectMQ
Dê aos seus dispositivos um endpoint MQTT padrão e bem suportado e mantenha o NATS para os seus serviços. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, conecte um dispositivo e sua ponte e acompanhe os dois lados no explorador de topics ao vivo.
Perguntas frequentes
O NATS é mais rápido que o MQTT?
Os dois têm baixa latência, e a velocidade no mundo real depende mais do servidor, da rede e das configurações de entrega do que do protocolo. Escolha com base nos clients e nos recursos, não na velocidade bruta.
Dispositivos IoT podem se conectar diretamente ao NATS?
Dispositivos de classe Linux podem usar clients NATS. Microcontroladores e sensores comerciais raramente suportam NATS, e é por isso que o MQTT domina a camada de dispositivos.
O NATS suporta clients MQTT?
O servidor NATS oferece uma interface MQTT 3.1.1 apoiada pelo JetStream. Ela não cobre recursos do MQTT 5, então um broker MQTT dedicado costuma ser mais adequado para frotas grandes e heterogêneas.
Qual é o equivalente no NATS a uma retained message do MQTT?
Os equivalentes mais próximos são um stream JetStream configurado para manter a última mensagem por subject ou um bucket key-value do JetStream. Os dois precisam ser configurados explicitamente.



