Normalement, un broker MQTT transmet un message aux clients abonnés à cet instant, puis l’oublie. Un client qui s’abonne une minute plus tard ne voit rien jusqu’à la publication suivante. Les messages retenus (retained) résolvent ce problème : le broker stocke le dernier message retenu d’un topic et le remet immédiatement à chaque nouvel abonné, qui démarre ainsi toujours avec l’état courant.
Comment fonctionnent les messages retenus
La rétention est contrôlée par un seul bit, le flag RETAIN du paquet PUBLISH. Lorsque le broker reçoit une publication avec RETAIN=1 :
- Il livre le message aux abonnés actuels, comme d’habitude.
- Il stocke le message (topic, payload, QoS) comme message retenu de ce topic, en remplaçant le précédent. Il y a au plus un message retenu par topic.
- Chaque fois qu’un client s’abonne ensuite avec un filtre correspondant au topic, le broker envoie le message retenu juste après le
SUBACK, avec le flag retain positionné pour que le client sache qu’il s’agit d’une valeur stockée.
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 instantlyLes abonnements avec jokers (wildcards) reçoivent les messages retenus de tous les topics correspondants : c’est ainsi qu’un tableau de bord abonné à acme/+/status peut afficher l’état de tous les appareils dès son démarrage.
Le flag retain à la livraison
En MQTT 3.1.1, un message transmis à un abonné déjà existant a toujours le flag retain à zéro ; le flag n’est positionné que lorsque le message est envoyé en raison d’un nouvel abonnement. MQTT 5 conserve ce comportement par défaut mais ajoute l’option d’abonnement Retain As Published, qui préserve le flag d’origine — utile pour les bridges.
Sans rétention, un tableau de bord fraîchement lancé afficherait des tuiles vides jusqu’à ce que chaque appareil publie à nouveau — ce qui, pour un capteur de porte ou une valeur de configuration, peut prendre des heures. Avec la rétention, le premier écran est déjà correct.
Quand utiliser les messages retenus
- État des appareils —
online/offline, marche/arrêt, mode courant. - Configuration et consignes — un appareil qui redémarre s’abonne et reçoit immédiatement sa configuration.
- Valeurs qui évoluent lentement — version du firmware, emplacement, dernière mesure connue.
- Présence, combinée à un message Last Will retenu, pour que le statut hors ligne persiste.
Évitez de retenir :
- Les événements et les commandes — une commande
unlock-doorretenue serait rejouée à chaque nouvel abonné, parfois des jours plus tard. - Les flux à haute fréquence — retenir est sans danger mais inutile quand la valeur suivante arrive dans la seconde.
- Les topics par message — des topics contenant des IDs ou des horodatages laissent derrière eux des milliers de messages retenus périmés.
Comment effacer un message retenu
Pour supprimer un message retenu, publiez sur le même topic avec le flag retain positionné et un payload de longueur nulle. Le broker supprime le message stocké et ne conserve pas le message vide. Les abonnés actuels reçoivent bien ce message vide : faites en sorte que votre code ignore les payloads vides.
# -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 });Pour effacer de nombreux topics d’un coup, abonnez-vous avec un joker, collectez chaque topic qui livre un message avec le flag retain, et publiez un payload retenu vide sur chacun. Il n’existe pas de commande standard « supprimer tous les messages retenus » — certains brokers proposent des outils d’administration, mais ils sont propres à chaque broker.
Messages retenus ou sessions persistantes
Les messages retenus sont souvent confondus avec les sessions persistantes, mais ils répondent à des questions différentes :
| Message retenu | Session persistante | |
|---|---|---|
| Portée | Par topic, partagé par tous les abonnés | Par client ID |
| Ce qui est conservé | Uniquement le dernier message | Les abonnements et chaque message QoS 1/2 manqué |
| Qui le reçoit | Tout client qui s’abonne plus tard | Uniquement ce client lors de sa reconnexion |
| Usage type | L’état courant | Ne manquer aucun événement |
Un appareil qui a besoin à la fois de sa configuration courante et de chaque commande envoyée pendant qu’il était hors ligne utilise les deux : un topic de configuration retenu et une session persistante pour le topic de commandes. Le guide de la QoS explique comment sessions et QoS interagissent.
Les messages retenus conservent aussi leur QoS. Lorsque le broker livre un message stocké à un nouvel abonné, la règle de rétrogradation habituelle s’applique : l’abonné le reçoit avec la plus basse des deux QoS, celle d’origine et celle de son abonnement.
Les messages retenus en MQTT 5
MQTT 5 offre un contrôle plus fin sur les messages retenus :
| Fonctionnalité | Rôle |
|---|---|
| Retain Handling (option d’abonnement) | 0 = envoyer les messages retenus à l’abonnement (par défaut), 1 = uniquement si l’abonnement est nouveau, 2 = ne jamais les envoyer |
| Retain As Published (option d’abonnement) | Conserve le flag retain d’origine sur les messages transmis |
| Message Expiry Interval (propriété de publication) | Le broker supprime le message retenu après le nombre de secondes indiqué |
| Retain Available (propriété du CONNACK) | Indique au client si le broker prend en charge les messages retenus |
L’expiration des messages est particulièrement pratique : une mesure de capteur retenue qui expire au bout d’une heure ne peut jamais être prise pour une valeur fraîche. Voir MQTT 5 vs 3.1.1 pour la liste complète des changements.
Tester les messages retenus
- Publiez
onlineavec Retain coché surtestmqtt/your-id/status. - Déconnectez-vous, reconnectez-vous et abonnez-vous à
testmqtt/your-id/#. Le message arrive instantanément, marqué comme retenu. - Publiez un payload vide avec Retain coché, puis réabonnez-vous — rien n’arrive. Le message retenu a disparu.
Essayez-le dans le client MQTT en ligne
Le client MQTT en ligne affiche un badge « retained » sur les messages stockés, ce qui permet de repérer facilement un état périmé. Pour une checklist plus large, consultez comment tester un broker MQTT.
Questions fréquentes
Comment supprimer un message retenu en MQTT ?
Publiez sur le même topic un message avec le flag retain positionné et un payload de longueur nulle (vide). Le broker supprime le message retenu stocké, et le message vide n’est pas conservé. Avec mosquitto_pub, utilisez -r -n.
Combien de messages retenus un topic peut-il avoir ?
Un seul. Le broker ne conserve que le message retenu le plus récent par topic ; chaque nouvelle publication retenue remplace la précédente.
Un message retenu est-il la même chose qu’une session persistante ?
Non. Un message retenu est la dernière valeur d’un topic, livrée à tout nouvel abonné. Une session persistante met en file d’attente les messages destinés à un client précis pendant qu’il est hors ligne. Ils résolvent des problèmes différents et sont souvent utilisés ensemble.