La consommation de bande passante MQTT est facile à estimer dès que l'on sait d'où vient chaque octet : le paquet MQTT lui-même, les en-têtes TCP/IP qui le transportent, le chiffrement TLS qui l'enveloppe et le trafic de fond des connexions et des keep alives. Ce guide calcule chaque couche pour un message de télémétrie réaliste en QoS 0, 1 et 2, puis transforme les chiffres en une estimation mensuelle des données que vous pourrez utiliser pour choisir un forfait cellulaire pour vos appareils.
Pourquoi MQTT est léger, et où passent malgré tout les octets
L'en-tête fixe de MQTT peut ne faire que deux octets, il n'y a pas d'en-têtes texte comme en HTTP, et une seule connexion de longue durée remplace une poignée de main par requête. Le surcoût protocolaire par message est donc minime. Mais sur un lien facturé au volume, vous payez des octets IP, pas des octets MQTT, et pour les petits payloads, ce sont les couches inférieures qui dominent. Un modèle mental utile comporte quatre couches :
| Couche | Coût par message | Remarques |
|---|---|---|
| Payload | Vos données | Souvent 20 à 200 octets de JSON pour la télémétrie |
| MQTT | 2 à 6 octets + nom du topic | La longueur du topic est souvent le plus gros coût MQTT |
| TLS | Environ 22 à 29 octets par enregistrement | Dépend de la version de TLS et de la suite de chiffrement |
| TCP/IP | 40 octets par segment (IPv4, sans options) | Souvent 52 avec les timestamps TCP ; 60 en IPv6 |
S'y ajoutent deux coûts de fond qui ne sont pas liés à chaque message : l'établissement de la connexion (TCP, poignée de main TLS, CONNECT) et les pings keep alive pendant l'inactivité. Les deux sont traités ci-dessous. Pour la disposition au niveau de l'octet de la couche MQTT, consultez le guide de la structure des paquets MQTT.
Surcoût MQTT par message selon la QoS
Prenons un exemple typique : MQTT 3.1.1, le topic plant1/line2/pump3/telemetry (28 caractères) et un payload JSON de 48 octets comme {"t":1760601600,"flow":12.4,"p":3.1,"temp":41.7}.
Le paquet PUBLISH en QoS 0 se compose de :
- En-tête fixe : 2 octets (type et flags, un octet de remaining length)
- Topic : préfixe de longueur de 2 octets + 28 octets = 30 octets
- Payload : 48 octets
- Total : 80 octets
En QoS 1 et 2, le PUBLISH gagne un packet identifier de 2 octets, et des paquets d'acquittement de 4 octets chacun s'ajoutent :
| QoS | Paquets sur le réseau | Octets MQTT | Surcoût par rapport au payload |
|---|---|---|---|
| 0 | PUBLISH (80) | 80 | 32 octets |
| 1 | PUBLISH (82) + PUBACK (4) | 86 | 38 octets |
| 2 | PUBLISH (82) + PUBREC + PUBREL + PUBCOMP (4 chacun) | 94 | 46 octets |
En MQTT 5, ajoutez un octet pour la longueur de propriétés vide dans le PUBLISH ; les acquittements de succès sans propriétés restent à 4 octets. Au niveau de la couche MQTT, le choix de la QoS ne modifie donc le coût que modestement. La vraie différence apparaît au niveau de la couche transport, car chaque paquet supplémentaire implique généralement un segment TCP supplémentaire. Le guide des niveaux de QoS MQTT explique quand les garanties de livraison supplémentaires en valent la peine.
Le nom du topic est souvent le plus gros coût MQTT
Dans l'exemple ci-dessus, le topic représente 30 des 32 octets de surcoût en QoS 0. Les topics profonds de style ISA-95 dépassent facilement 50 caractères. Deux remèdes : garder des topics concis côté appareil, ou utiliser les topic aliases de MQTT 5, qui remplacent le topic par un nombre de 2 octets après la première publication. Le guide des topic aliases MQTT détaille les économies.
Ajouter TCP/IP et TLS
Chaque paquet MQTT envoyé isolément voyage dans un segment TCP avec au moins 40 octets d'en-têtes IPv4 et TCP. Le récepteur acquitte les données par des ACK TCP, qui sont aussi des segments de 40 octets, sauf s'ils peuvent être portés par des données circulant dans l'autre sens. Le comportement du delayed ACK varie selon le système d'exploitation et la pile réseau : considérez donc le coût des ACK comme approximatif.
TLS enveloppe chaque écriture dans un enregistrement. Avec TLS 1.3 et une suite AES-GCM, chaque enregistrement ajoute 5 octets d'en-tête, 1 octet de type de contenu interne et un tag d'authentification de 16 octets : 22 octets. TLS 1.2 avec AES-GCM ajoute 29 octets, en raison d'un nonce explicite de 8 octets.
En réunissant le tout pour un message de télémétrie, en IPv4 sans options TCP, TLS 1.3, en comptant un ACK TCP pur par segment de données :
| QoS | TCP simple (port 1883) | TLS 1.3 (port 8883) |
|---|---|---|
| 0 | 80 + 40 + 40 ACK = 160 octets | 102 + 40 + 40 ACK = 182 octets |
| 1 | 122 + 44 + 40 ACK = 206 octets | 144 + 66 + 40 ACK = 250 octets |
| 2 | 122 + 3 x 44 + 2 ACK, environ 335 octets | 144 + 3 x 66 + 2 ACK, environ 420 octets |
Pour un payload de 48 octets, le coût sur le réseau représente environ quatre à huit fois les données. Ce rapport diminue à mesure que les payloads grossissent : un payload de 1 Ko a presque le même surcoût absolu, qui devient alors une petite fraction. C'est pourquoi regrouper les mesures, par exemple un message avec dix échantillons au lieu de dix messages, est l'optimisation de bande passante la plus efficace.
TLS n'est pas facultatif pour les déploiements réels et, comme le montre le tableau, son coût par message est modeste. Son coût le plus important est la poignée de main.
Coûts d'établissement de la connexion
Chaque nouvelle connexion paie :
- La poignée de main TCP : trois segments, environ 120 à 180 octets.
- La poignée de main TLS : généralement quelques kilo-octets, principalement la chaîne de certificats du serveur. La reprise de session TLS 1.3, si votre bibliothèque la prend en charge, réduit fortement ce coût.
- CONNECT et CONNACK : un CONNECT avec un client ID de 20 caractères, un nom d'utilisateur et un mot de passe pèse environ 80 octets ; le CONNACK fait 4 octets en MQTT 3.1.1.
- SUBSCRIBE et SUBACK pour chaque abonnement, si vous n'utilisez pas de session persistante.
Une seule reconnexion peut donc coûter autant que des dizaines de messages de télémétrie. Les appareils qui se connectent, publient une fois et se déconnectent chaque minute gaspillent l'essentiel de leurs données en poignées de main. Sauf si l'appareil dort pendant de longues périodes, gardez la connexion ouverte et utilisez une session persistante pour ne pas avoir à vous réabonner après chaque reconnexion. Le guide des sessions persistantes explique comment faire.
Coûts du keep alive
Lorsqu'un client n'a rien à envoyer pendant l'intervalle de keep alive, il envoie un PINGREQ (2 octets) et le broker répond par un PINGRESP (2 octets). Avec TLS 1.3 et TCP/IP, un échange de ping représente environ 64 + 64 octets, plus un ACK : environ 170 octets.
| Keep alive | Pings par jour en inactivité | Données approximatives par jour |
|---|---|---|
| 30 s | 2 880 | environ 485 Ko |
| 60 s | 1 440 | environ 240 Ko |
| 300 s | 288 | environ 48 Ko |
| 900 s | 96 | environ 16 Ko |
Les pings ne sont envoyés que lorsque la connexion est par ailleurs inactive : un appareil qui publie toutes les 30 secondes avec un keep alive de 60 secondes n'envoie donc aucun ping. Des intervalles plus longs économisent des données mais exposent aux timeouts NAT des réseaux cellulaires, qui coupent les connexions inactives et imposent une reconnexion coûteuse. Réglez-le à l'aide des conseils de l'article sur l'intervalle keep alive MQTT.
Estimer les données mensuelles d'un appareil cellulaire
Ce calculateur Python combine tous les éléments. Ajustez les paramètres à votre appareil :
def mqtt_monthly_bytes(
payload=48, topic_len=28, qos=1, msgs_per_day=1440,
tls=True, reconnects_per_day=2, handshake_bytes=5000,
keepalive_s=120, idle_seconds_per_day=0,
):
ip_tcp = 40
tls_rec = 22 if tls else 0
publish = 2 + 2 + topic_len + payload + (2 if qos else 0)
def seg(mqtt_bytes):
return mqtt_bytes + tls_rec + ip_tcp
if qos == 0:
per_msg = seg(publish) + ip_tcp
elif qos == 1:
per_msg = seg(publish) + seg(4) + ip_tcp
else:
per_msg = seg(publish) + 3 * seg(4) + 2 * ip_tcp
pings = idle_seconds_per_day / keepalive_s if keepalive_s else 0
ping_bytes = pings * (2 * seg(2) + ip_tcp)
connect_bytes = reconnects_per_day * (handshake_bytes if tls else 300)
per_day = msgs_per_day * per_msg + ping_bytes + connect_bytes
return per_day * 30
for qos in (0, 1, 2):
mb = mqtt_monthly_bytes(qos=qos) / 1_000_000
print(f"QoS {qos}: {mb:.1f} MB per month")
Avec un message par minute en QoS 1 sur TLS, le résultat est d'environ 11 Mo par mois et par appareil, dont seule une petite part provient des deux reconnexions supposées. Passez msgs_per_day à 144 (toutes les dix minutes) avec un keep alive de 300 secondes et le temps d'inactivité ajouté, et le total chute fortement. Il s'agit d'estimations calculées, pas de mesures ; validez-les en vérifiant la consommation réelle sur une carte SIM de test ou en capturant le trafic pendant une journée avec tcpdump et en additionnant les octets.
Check-list pour réduire la bande passante
- Regroupez les échantillons dans des messages moins nombreux et plus gros lorsque la latence le permet.
- Utilisez des payloads compacts : clés JSON courtes, CBOR ou Protobuf. Consultez le format de payload MQTT.
- Raccourcissez les topics des appareils ou utilisez les topic aliases avec MQTT 5.
- Choisissez la QoS par topic : QoS 0 pour la télémétrie fréquente où une perte occasionnelle est acceptable, QoS 1 pour les événements et les commandes.
- Gardez les connexions ouvertes et utilisez des sessions persistantes au lieu de vous reconnecter à chaque message.
- Réglez le keep alive sur la valeur la plus longue que permet le timeout NAT de votre réseau.
- Publiez sur changement plutôt qu'à fréquence fixe lorsque les valeurs sont stables.
- Évitez les abonnements inutiles : un abonnement avec wildcard sur un appareil reçoit chaque message correspondant, ce qui consomme des données descendantes.
Des appareils efficaces sur ConnectMQ
ConnectMQ prend en charge MQTT 3.1.1 et 5.0, y compris les topic aliases et la session expiry, en TLS sur le port 8883 avec un certificat Let's Encrypt : les optimisations ci-dessus fonctionnent donc sans configuration particulière. Prototypez sur le serveur MQTT public gratuit, réservé aux tests et aux prototypes, puis mesurez le trafic réel sur un broker privé. Le tutoriel MQTT couvre les fondamentaux si vous découvrez le protocole.
Démarrer avec ConnectMQ
Un broker MQTT managé vous permet de vous concentrer sur l'efficacité de vos appareils plutôt que sur l'exploitation de serveurs. Créez un broker Serverless (Free) sur app.connectmq.com, sans carte bancaire, et utilisez l'explorateur de topics en direct pour voir exactement ce qu'envoient vos appareils. Pour une comparaison plus large, lisez notre guide pour choisir un broker MQTT cloud.
Questions fréquentes
Quel surcoût MQTT ajoute-t-il par message ?
Au niveau de la couche MQTT, un PUBLISH ajoute 4 octets plus le nom du topic en QoS 0, et 6 octets plus le topic en QoS 1 et 2, avant les acquittements. TCP/IP et TLS ajoutent par-dessus environ 60 octets ou plus par paquet.
TLS rend-il MQTT beaucoup plus coûteux ?
Par message, TLS 1.3 ajoute environ 22 octets par enregistrement, ce qui est modeste. Le coût le plus important est la poignée de main de quelques kilo-octets à chaque nouvelle connexion : gardez donc les connexions ouvertes plutôt que de vous reconnecter fréquemment.
Combien de données le keep alive MQTT consomme-t-il ?
Un échange de ping coûte quelques octets au niveau MQTT, mais environ 170 octets avec TCP, IP et TLS. Avec un intervalle de 60 secondes sur une connexion inactive, cela représente environ 240 Ko par jour.
La QoS 0 est-elle toujours la moins chère ?
Oui, en octets, car elle n'envoie aucun paquet d'acquittement. Mais si des messages perdus obligent votre application à renvoyer des données ou à interroger, la QoS 1 peut finalement revenir moins cher.



