{"id":1516,"date":"2025-05-23T20:47:40","date_gmt":"2025-05-23T18:47:40","guid":{"rendered":"https:\/\/www.rocworks.at\/wordpress\/?p=1516"},"modified":"2025-05-23T20:47:40","modified_gmt":"2025-05-23T18:47:40","slug":"retained-messages-are-the-devil-of-mqtt-%f0%9f%98%88-%f0%9f%98%b1","status":"publish","type":"post","link":"https:\/\/www.rocworks.at\/wordpress\/?p=1516","title":{"rendered":"Retained messages are the devil of MQTT \ud83d\ude08 \ud83d\ude31"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">MQTT brokers handle retained messages differently &#8211; and that can have serious implications&#8230;<br><br>\ud83d\udd38 HiveMQ Community Edition doesn\u2019t support to persist retained messages to disk. After a restart, they\u2019re gone &#8211; so it\u2019s better to go with the Enterprise Edition. Unfortunately I do not have access to the Enterprise version to perform further tests.<br><br>\ud83d\udd38 Mosquitto writes retained messages to disk periodically(!), default is 30 minutes! And during writing from memory to disk, publishing values pauses, it seems the broker gets frozen during writing to disk. Writing 1M retained messages to disk takes time&#8230; plus, I got it to crash at about 4460000 retained values (reproducible), and after the crash, it didn&#8217;t start anymore &#8211; until I removed the database file and lost all retained messages.<br><br>\ud83d\udd38 EMQX handled the test with a max of 2000 value changes per second. It was already using about 250% CPU of four cores, and I occasionally received \u201cMnesia is overloaded\u201d warnings. I don\u2019t know whether messages are being queued or dropped at that point. Writing to disk didn\u2019t seem fast. Additionally, a broker startup after storing 1 million retained messages took a while (about 30 seconds), likely because all values are being loaded into memory.<br><br>\ud83d\udd38 BifroMQ handled the test at around 8000 v\/s, using only about 20% of four CPU cores. I noticed that throughput decreases as the number of published topics increases. Interestingly, it limits wildcard subscriptions to just 10 retained messages &#8211; to protect the system, but that number feels a bit low. I couldn\u2019t find a configuration setting to change it.<br><br>\ud83d\udd38 MonsterMQ handled the test with about 7000 v\/s with 18% for the Monster plus 70% for the PostgreSQL database of four CPU cores. MonsterMQ stores retained messages in a PostgreSQL table (written in bulk). If you have a high volume of retained messages, it can lead to full queues &#8211; especially if your PostgreSQL instance can&#8217;t keep up. In that case, the broker will not persist all values.<br><br>\ud83e\udde8 Be careful when using retained messages!<br><br>\ud83d\udc49 Understand and test your broker\u2019s behavior before relying on them for data durability.<br><br>Just to note: These results are based on my own tests and specific use cases, and were performed on modest hardware. I was publishing retained messages to hierarchically structured topics (e.g., root\/0\/0\/0\/0\/0\/0\/0\/0\/0\/0), using numbers from 0 to 9, without any subscribers.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>MQTT brokers handle retained messages differently &#8211; and that can have serious implications&#8230; \ud83d\udd38 HiveMQ Community Edition doesn\u2019t support to persist retained messages to disk. After a restart, they\u2019re gone &#8211; so it\u2019s better to go with the Enterprise Edition. &hellip; <a href=\"https:\/\/www.rocworks.at\/wordpress\/?p=1516\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[79,67],"tags":[],"class_list":["post-1516","post","type-post","status-publish","format-standard","hentry","category-monstermq","category-mqtt"],"_links":{"self":[{"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1516","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1516"}],"version-history":[{"count":1,"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1516\/revisions"}],"predecessor-version":[{"id":1517,"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1516\/revisions\/1517"}],"wp:attachment":[{"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1516"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1516"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rocworks.at\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1516"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}