Normalmente, um broker MQTT encaminha uma mensagem aos clientes que estão inscritos naquele momento e depois a esquece. Um cliente que assina o tópico um minuto depois não vê nada até a próxima publicação. As mensagens retidas (retained) resolvem isso: o broker guarda a última mensagem retida de um tópico e a entrega imediatamente a cada novo assinante, que assim sempre começa com o estado atual.
Como funcionam as mensagens retidas
A retenção é controlada por um único bit, a flag RETAIN do pacote PUBLISH. Quando o broker recebe uma publicação com RETAIN=1:
- Entrega a mensagem aos assinantes atuais, como de costume.
- Armazena a mensagem (tópico, payload, QoS) como a mensagem retida daquele tópico, substituindo a anterior. Existe no máximo uma mensagem retida por tópico.
- Sempre que um cliente assina depois com um filtro que corresponde ao tópico, o broker envia a mensagem retida logo após o
SUBACK, com a flag retain ativada para que o cliente saiba que se trata de um valor armazenado.
10:00 device PUBLISH acme/th-01/setpoint "21.0" retain=1 -> broker stores it
10:05 device PUBLISH acme/th-01/setpoint "22.5" retain=1 -> replaces "21.0"
10:30 app SUBSCRIBE acme/+/setpoint
10:30 broker PUBLISH acme/th-01/setpoint "22.5" retain=1 -> delivered instantlyAssinaturas com curingas recebem as mensagens retidas de todos os tópicos correspondentes — é assim que um dashboard que assina acme/+/status consegue exibir o estado de todos os dispositivos logo ao iniciar.
A flag retain na entrega
No MQTT 3.1.1, uma mensagem encaminhada a um assinante já existente sempre tem a flag retain desativada; a flag só vem ativada quando a mensagem é enviada por causa de uma nova assinatura. O MQTT 5 mantém esse padrão, mas adiciona a opção de assinatura Retain As Published, que preserva a flag original — útil para bridges.
Sem retenção, um dashboard recém-iniciado mostraria blocos vazios até que cada dispositivo publicasse de novo — o que, para um sensor de porta ou um valor de configuração, poderia levar horas. Com retenção, a primeira tela já aparece correta.
Quando usar mensagens retidas
- Estado do dispositivo —
online/offline, ligado/desligado, modo atual. - Configuração e setpoints — um dispositivo que reinicia assina o tópico e recebe sua configuração na hora.
- Valores que mudam pouco — versão do firmware, localização, última leitura conhecida.
- Presença, junto com uma mensagem Last Will retida, para que o status offline permaneça.
Evite reter:
- Eventos e comandos — um comando
unlock-doorretido seria reenviado a cada novo assinante, possivelmente dias depois. - Fluxos de alta frequência — reter não faz mal, mas é inútil quando o próximo valor chega em um segundo.
- Tópicos por mensagem — tópicos que contêm IDs ou timestamps deixam para trás milhares de mensagens retidas obsoletas.
Como limpar uma mensagem retida
Para apagar uma mensagem retida, publique no mesmo tópico com a flag retain ativada e um payload de tamanho zero. O broker remove a mensagem armazenada e não guarda a vazia. Os assinantes atuais recebem a mensagem vazia, então faça seu código ignorar payloads vazios.
# -r = retain, -n = send a null (zero-length) payload
mosquitto_pub -h broker.hivemq.com -t 'testmqtt/demo/status' -r -nclient.publish('testmqtt/demo/status', '', { retain: true, qos: 1 });Para limpar muitos tópicos de uma vez, assine com um curinga, colete todos os tópicos que entregam uma mensagem com a flag retain e publique um payload retido vazio em cada um. Não existe um comando padrão de "apagar todas as retidas" — alguns brokers oferecem ferramentas administrativas, mas elas são específicas de cada broker.
Mensagens retidas vs sessões persistentes
Mensagens retidas costumam ser confundidas com sessões persistentes, mas elas respondem a perguntas diferentes:
| Mensagem retida | Sessão persistente | |
|---|---|---|
| Escopo | Por tópico, compartilhada por todos os assinantes | Por client ID |
| O que é guardado | Apenas a mensagem mais recente | As assinaturas e todas as mensagens QoS 1/2 perdidas |
| Quem recebe | Qualquer cliente que assine depois | Somente aquele cliente, ao reconectar |
| Uso típico | Estado atual | Não perder eventos |
Um dispositivo que precisa tanto da sua configuração atual quanto de todos os comandos enviados enquanto estava offline usa os dois: um tópico de configuração retido e uma sessão persistente para o tópico de comandos. O guia de QoS explica como sessões e QoS interagem.
Mensagens retidas também mantêm o seu QoS. Quando o broker entrega uma mensagem armazenada a um novo assinante, vale a regra de rebaixamento de sempre: o assinante a recebe com o menor entre o QoS original e o QoS da sua assinatura.
Mensagens retidas no MQTT 5
O MQTT 5 adiciona um controle mais fino sobre as mensagens retidas:
| Recurso | O que faz |
|---|---|
| Retain Handling (opção de assinatura) | 0 = envia as mensagens retidas ao assinar (padrão), 1 = só se a assinatura for nova, 2 = nunca envia |
| Retain As Published (opção de assinatura) | Mantém a flag retain original nas mensagens encaminhadas |
| Message Expiry Interval (propriedade de publicação) | O broker descarta a mensagem retida após o número de segundos indicado |
| Retain Available (propriedade do CONNACK) | Informa ao cliente se o broker suporta mensagens retidas |
A expiração de mensagens é especialmente útil: uma leitura de sensor retida que expira após uma hora nunca será confundida com uma leitura recente. Veja MQTT 5 vs 3.1.1 para a lista completa de mudanças.
Teste as mensagens retidas
- Publique
onlinecom Retain marcado emtestmqtt/your-id/status. - Desconecte, reconecte e assine
testmqtt/your-id/#. A mensagem chega na hora, marcada como retida. - Publique um payload vazio com Retain marcado e assine de novo — nada chega. A mensagem retida foi apagada.
O cliente MQTT online mostra um selo de retida nas mensagens armazenadas, o que facilita identificar estados obsoletos. Para um checklist mais amplo, veja como testar um broker MQTT.
Perguntas frequentes
Como apago uma mensagem retida no MQTT?
Publique no mesmo tópico uma mensagem com a flag retain ativada e um payload de tamanho zero (vazio). O broker remove a mensagem retida armazenada, e a mensagem vazia não é guardada. Com o mosquitto_pub, use -r -n.
Quantas mensagens retidas um tópico pode ter?
Uma. O broker guarda apenas a mensagem retida mais recente de cada tópico; cada nova publicação retida substitui a anterior.
Uma mensagem retida é o mesmo que uma sessão persistente?
Não. Uma mensagem retida é o último valor de um tópico, entregue a qualquer novo assinante. Uma sessão persistente enfileira mensagens para um cliente específico enquanto ele está offline. Elas resolvem problemas diferentes e costumam ser usadas juntas.