diff --git a/public/_redirects b/public/_redirects index 367551dddb..c9fcb86309 100644 --- a/public/_redirects +++ b/public/_redirects @@ -1053,6 +1053,13 @@ /products/mqtt-broker/privacy-policy/ https://tbmq.io/product/privacy-policy/ 301 /products/mqtt-broker/terms-of-use/ https://tbmq.io/product/terms-of-use/ 301 /resources/tbmq-demo-root-ca.pem https://tbmq.io/resources/tbmq-demo-root-ca.pem 301 +/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/ https://tbmq.io/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/ 301 +/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/ https://tbmq.io/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/ 301 +/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more/ https://tbmq.io/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more/ 301 +/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/ https://tbmq.io/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/ 301 +/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/ https://tbmq.io/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/ 301 +/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/ https://tbmq.io/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/ 301 +/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/ https://tbmq.io/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/ 301 /products/trendz/trndz-request-demo/ /products/trendz/request-demo/ 301 /images/trendz/trndz-request-demo/ /products/trendz/request-demo/ 301 /products/paas/billing-info/ /docs/paas/user-guide/billing-info/ 301 diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-1M-Redis-V2.svg b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-1M-Redis-V2.svg deleted file mode 100644 index 58b26844fc..0000000000 --- a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-1M-Redis-V2.svg +++ /dev/null @@ -1,710 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-600k-Redis-V1.svg b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-600k-Redis-V1.svg deleted file mode 100644 index 5548bf3116..0000000000 --- a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-600k-Redis-V1.svg +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-Postrgres-2.svg b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-Postrgres-2.svg deleted file mode 100644 index fad67f940c..0000000000 --- a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-Postrgres-2.svg +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/TBMQ-fan-in-application-clients.svg b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/TBMQ-fan-in-application-clients.svg deleted file mode 100644 index 3a459dc73d..0000000000 --- a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/TBMQ-fan-in-application-clients.svg +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/atomicity_with_lua_scripting_2x.webp b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/atomicity_with_lua_scripting_2x.webp deleted file mode 100644 index a71259d31f..0000000000 Binary files a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/atomicity_with_lua_scripting_2x.webp and /dev/null differ diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/cover.webp b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/cover.webp deleted file mode 100644 index b85cc3f487..0000000000 Binary files a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/cover.webp and /dev/null differ diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/migration_from_jedis_to_lettuce.webp b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/migration_from_jedis_to_lettuce.webp deleted file mode 100644 index b0205eb694..0000000000 Binary files a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/migration_from_jedis_to_lettuce.webp and /dev/null differ diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/redis-cluster.png b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/redis-cluster.png deleted file mode 100644 index a0cb1bf75e..0000000000 Binary files a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/redis-cluster.png and /dev/null differ diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/schedule.webp b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/schedule.webp deleted file mode 100644 index ef6d869d87..0000000000 Binary files a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/schedule.webp and /dev/null differ diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/screenshot_from_2025_01_03_16_37_17_1x.webp b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/screenshot_from_2025_01_03_16_37_17_1x.webp deleted file mode 100644 index 1f865475e3..0000000000 Binary files a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/screenshot_from_2025_01_03_16_37_17_1x.webp and /dev/null differ diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/screenshot_from_2025_01_03_16_45_49_1x.webp b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/screenshot_from_2025_01_03_16_45_49_1x.webp deleted file mode 100644 index bb6f38fc08..0000000000 Binary files a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/screenshot_from_2025_01_03_16_45_49_1x.webp and /dev/null differ diff --git a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/table-1.webp b/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/table-1.webp deleted file mode 100644 index 25a983413d..0000000000 Binary files a/public/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/table-1.webp and /dev/null differ diff --git a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/ce_pe-1.webp b/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/ce_pe-1.webp deleted file mode 100644 index 39b510e7c5..0000000000 Binary files a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/ce_pe-1.webp and /dev/null differ diff --git a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/cover.webp b/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/cover.webp deleted file mode 100644 index 8e71d0c9f4..0000000000 Binary files a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/cover.webp and /dev/null differ diff --git a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/rbac.webp b/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/rbac.webp deleted file mode 100644 index c4c109b764..0000000000 Binary files a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/rbac.webp and /dev/null differ diff --git a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/sso.webp b/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/sso.webp deleted file mode 100644 index 20f350db7f..0000000000 Binary files a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/sso.webp and /dev/null differ diff --git a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/white_labeling-1.webp b/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/white_labeling-1.webp deleted file mode 100644 index b786d58482..0000000000 Binary files a/public/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/white_labeling-1.webp and /dev/null differ diff --git a/public/images/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more/cover.webp b/public/images/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more/cover.webp deleted file mode 100644 index 5f1789bef8..0000000000 Binary files a/public/images/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more/cover.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-02.webp b/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-02.webp deleted file mode 100644 index 930459af9e..0000000000 Binary files a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-02.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-1.webp b/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-1.webp deleted file mode 100644 index c6c237b042..0000000000 Binary files a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-1.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-4.webp b/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-4.webp deleted file mode 100644 index 4dbedc7744..0000000000 Binary files a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-4.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-6-2.webp b/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-6-2.webp deleted file mode 100644 index 672f8236b8..0000000000 Binary files a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-6-2.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/cover.webp b/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/cover.webp deleted file mode 100644 index 191b775137..0000000000 Binary files a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/cover.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/subscriptions.webp b/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/subscriptions.webp deleted file mode 100644 index 22c7227f80..0000000000 Binary files a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/subscriptions.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/unauthoraized-clients.webp b/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/unauthoraized-clients.webp deleted file mode 100644 index 60bf1faeaa..0000000000 Binary files a/public/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/unauthoraized-clients.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/cover.webp b/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/cover.webp deleted file mode 100644 index a286de9545..0000000000 Binary files a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/cover.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/helm-tbmq2.webp b/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/helm-tbmq2.webp deleted file mode 100644 index 9194057a2d..0000000000 Binary files a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/helm-tbmq2.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/http-1.webp b/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/http-1.webp deleted file mode 100644 index bf91d3c8bf..0000000000 Binary files a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/http-1.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/integration-executor-4.webp b/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/integration-executor-4.webp deleted file mode 100644 index 4a96e7bf90..0000000000 Binary files a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/integration-executor-4.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/kafka-1.webp b/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/kafka-1.webp deleted file mode 100644 index d15ffb08c8..0000000000 Binary files a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/kafka-1.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/mqtt-1.webp b/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/mqtt-1.webp deleted file mode 100644 index 9b23e79521..0000000000 Binary files a/public/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/mqtt-1.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/blocked_clients_3x.webp b/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/blocked_clients_3x.webp deleted file mode 100644 index 3fd5983faa..0000000000 Binary files a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/blocked_clients_3x.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/cover.webp b/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/cover.webp deleted file mode 100644 index a9a8207562..0000000000 Binary files a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/cover.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/jwt_authentication_3x.webp b/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/jwt_authentication_3x.webp deleted file mode 100644 index fe22933a9c..0000000000 Binary files a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/jwt_authentication_3x.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/mqtt_authentication_providers.webp b/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/mqtt_authentication_providers.webp deleted file mode 100644 index dba7be3c73..0000000000 Binary files a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/mqtt_authentication_providers.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/mqtt_backpressure.webp b/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/mqtt_backpressure.webp deleted file mode 100644 index 1be4afb7cb..0000000000 Binary files a/public/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/mqtt_backpressure.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/cover.webp b/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/cover.webp deleted file mode 100644 index 04db93b8cf..0000000000 Binary files a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/cover.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-audit-logs.webp b/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-audit-logs.webp deleted file mode 100644 index dcfc0f3f07..0000000000 Binary files a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-audit-logs.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-bulk-import.webp b/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-bulk-import.webp deleted file mode 100644 index 1fd19f97b5..0000000000 Binary files a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-bulk-import.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-http-auth.webp b/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-http-auth.webp deleted file mode 100644 index 7ee9adf352..0000000000 Binary files a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-http-auth.webp and /dev/null differ diff --git a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-sso-roles.webp b/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-sso-roles.webp deleted file mode 100644 index 1f0e8ba500..0000000000 Binary files a/public/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-sso-roles.webp and /dev/null differ diff --git a/src/content/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker.mdx b/src/content/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker.mdx deleted file mode 100644 index 38538ddc94..0000000000 --- a/src/content/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker.mdx +++ /dev/null @@ -1,344 +0,0 @@ ---- -title: '1 Million reasons to choose TBMQ as a high-performance MQTT broker' -description: 'TBMQ 2.x handles 1 million MQTT messages per second for persistent sessions with no single point of failure — architecture and performance walkthrough.' -date: 2025-02-07 -updatedDate: 2025-02-12 -author: dmytro-shvaika -categories: ['guides', 'tech', 'updates'] -featuredImage: '/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/cover.webp' -featuredImageAlt: '1M reasons to choose TBMQ as MQTT broker' -draft: false ---- - -Can an open-source MQTT broker handle one million messages per second for persistent sessions? TBMQ 2.x [proves](https://tbmq.io/docs/reference/1m-throughput-p2p-performance-test/) it can! Even more importantly, it achieves this with no single point of failure and ensures no data loss, even when hardware fails, making it a robust self-hosted MQTT broker solution for IIoT applications. - -This article dives into the architectural decisions and performance improvements that define the recent [2.0.x releases](https://tbmq.io/docs/releases/#v201-december-31-2024) of TBMQ, focusing on how these changes optimize persistent session handling, enhance P2P messaging, and improve overall system efficiency within a scalable IoT architecture. - -We hope this article offers valuable insights for software engineers looking for ideas and patterns to offload database workloads to persistent caching layers, helping to improve scalability and performance in their systems. Additionally, for those exploring a Mosquitto alternative, TBMQ stands out as a powerful and fault-tolerant MQTT broker option. - -## Fan-in pattern - -While the TBMQ 1.x version can [handle](https://tbmq.io/docs/reference/100m-connections-performance-test/) 100 million clients at once and [dispatches](https://tbmq.io/docs/reference/3m-throughput-single-node-performance-test/) 3 million messages per second, as a high-performance MQTT broker it was primarily designed to aggregate data from IoT devices and deliver it to back-end applications reliably (QoS 1). This architecture is based on our experience with IIoT and other large-scale IoT deployments, where millions of devices transmit data to a limited number of applications. - -Through these deployments, we recognized that IoT devices and applications follow distinct communication patterns. IoT devices or sensors publish data frequently but subscribe to relatively few topics or updates. In contrast, applications subscribe to data from tens or even hundreds of thousands of devices and require reliable message delivery. Additionally, applications often experience periods of downtime due to system maintenance, upgrades, failover scenarios, or temporary network disruptions. - -To address these differences, TBMQ introduces a key feature: the classification of MQTT clients as either standard (IoT devices) or [application](https://tbmq.io/docs/architecture/#persistent-application-client) clients. This distinction enables optimized handling of persistent MQTT sessions for applications. Specifically, each persistent application client is assigned a separate Kafka topic. This approach ensures efficient message persistence and retrieval when an MQTT client reconnects, improving overall reliability and performance. Additionally, application clients support MQTT’s shared subscription feature, allowing multiple instances of an application to efficiently distribute message processing. - -![TBMQ fan-in pattern with multiple application clients consuming MQTT messages](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/TBMQ-fan-in-application-clients.svg) - -[Kafka](https://kafka.apache.org/) serves as one of the core components. Designed for high-throughput, distributed messaging, Kafka efficiently handles large volumes of data streams, making it an ideal choice for TBMQ. With the latest Kafka versions capable of managing a huge number of topics, this architecture is well-suited for enterprise-scale deployments. - -## P2P pattern - -Unlike the fan-in, the point-to-point (P2P) communication pattern enables direct message exchange between MQTT clients. Typically implemented using uniquely defined topics, P2P is well-suited for private messaging, device-to-device communication, command transmission, and other direct interaction use cases. - -One of the key differences between fan-in and peer-to-peer MQTT messaging is the volume and flow of messages. In a P2P scenario, subscribers do not handle high message volumes, making it unnecessary to allocate dedicated Kafka topics and consumer threads to each MQTT client. Instead, the primary requirements for P2P message exchange are low latency and reliable message delivery, even for clients that may go offline temporarily. To meet these needs, TBMQ optimizes persistent session management for standard MQTT clients, which include IoT devices. - -![TBMQ peer-to-peer performance test with PostgreSQL backend](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-Postrgres-2.svg) - -In TBMQ 1.x, standard MQTT clients relied on PostgreSQL for message persistence and retrieval, ensuring that messages were delivered when a client reconnected. While PostgreSQL performed well initially, it had a fundamental limitation—it could only scale vertically. We anticipated that as the number of persistent MQTT sessions grew, PostgreSQL’s architecture would eventually become a bottleneck. To address this, we explored more scalable alternatives capable of handling the increasing demands of our MQTT broker. Redis was quickly chosen as the best fit due to its horizontal scalability, native clustering support, and widespread adoption. - -## PostgreSQL usage and limitations - -To fully understand the reasoning behind this shift, it’s important to first examine how MQTT clients operated within the PostgreSQL architecture. This architecture was built around two key tables. - -The `device_session_ctx` table was responsible for maintaining the session state of each persistent MQTT client: - -``` -Table "public.device_session_ctx" - Column | Type | Collation | Nullable | Default ---------------------+------------------------+-----------+----------+--------- - client_id | character varying(255) | | not null | - last_updated_time | bigint | | not null | - last_serial_number | bigint | | | - last_packet_id | integer | | | -Indexes: - "device_session_ctx_pkey" PRIMARY KEY, btree (client_id) -``` - -The key columns are `last_packet_id` and `last_serial_number`, which is used to maintain message order for persistent MQTT clients: - -- `last_packet_id` represents the packet ID of the last MQTT message received. -- `last_serial_number` acts as a continuously increasing counter, preventing message order issues when the MQTT packet ID wraps around after reaching its limit of `65535`. - -The `device_publish_msg` table was responsible for storing messages that must be published to persistent MQTT clients (subscribers). - -``` -Table "public.device_publish_msg" - Column | Type | Collation | Nullable | Default ---------------------------+------------------------+-----------+----------+--------- - client_id | character varying(255) | | not null | - serial_number | bigint | | not null | - topic | character varying | | not null | - time | bigint | | not null | - packet_id | integer | | | - packet_type | character varying(255) | | | - qos | integer | | not null | - payload | bytea | | not null | - user_properties | character varying | | | - retain | boolean | | | - msg_expiry_interval | integer | | | - payload_format_indicator | integer | | | - content_type | character varying(255) | | | - response_topic | character varying(255) | | | - correlation_data | bytea | | | -Indexes: - "device_publish_msg_pkey" PRIMARY KEY, btree (client_id, serial_number) - "idx_device_publish_msg_packet_id" btree (client_id, packet_id) -``` - -The key columns to highlight: - -- `time` – captures the system time (timestamp) when the message is stored. This field is used for periodic cleanup of expired messages. -- `msg_expiry_interval` – represents the expiration time (in seconds) for a message. This is set only for incoming MQTT 5 messages that include an expiry property. If the expiry property is absent, the message does not have a specific expiration time and remains valid until it is removed by time or size-based cleanup. - -Together, these tables manage message persistence and session state. The `device_session_ctx` table is designed for fast retrieval of the last MQTT packet ID and serial number stored for each persistent MQTT client. When messages for a client are received from a shared Kafka topic, the broker queries this table to fetch the latest values. These values are incremented sequentially and assigned to each message before being saved to the `device_publish_msg` table. - -While this design ensured reliable message delivery, it also introduced performance constraints. To better understand its limitations, we conducted prototype testing to evaluate PostgreSQL’s performance under the P2P communication pattern. Using a single instance with 64GB RAM and 12 CPU cores, we simulated message loads with a dedicated [performance testing tool](https://github.com/thingsboard/tb-mqtt-perf-tests/tree/p2p-perf-test) capable of generating MQTT clients and simulating the desired message load. The primary performance metric was the average message processing latency — measured from the moment the message was published to the point it was acknowledged by the subscriber. The test was considered successful only if there was no performance degradation, meaning the broker consistently maintained an average latency in the two-digit millisecond range. - -With the prototype testing, we ultimately reach the **limit** at 30k msg/s throughput utilizing PostgreSQL as a persistence message storage. Throughput refers to the total number of messages per second, including both incoming and outgoing messages. - -![TBMQ message scheduling and processing diagram](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/schedule.webp) -*The graph reflects 75k tuples in/5s, corresponding to 15k msg/s for persistent MQTT clients, or half of the 30k msg/s throughput measured.* - -Based on the TimescaleDB blog [post](https://www.timescale.com/blog/postgresql-timescaledb-1000x-faster-queries-90-data-compression-and-much-more#ingest-performance), vanilla PostgreSQL can handle up to 300k inserts per second under ideal conditions. However, this performance depends on factors such as hardware, workload, and table schema. While vertical scaling can provide some improvement, PostgreSQL’s per-table insert throughput eventually reaches a hard limit. Confident that Redis could overcome this bottleneck, we began the migration process to achieve greater scalability and efficiency. - -## Redis as a scalable alternative - -Our decision to migrate to Redis was driven by its ability to address the core performance bottlenecks encountered with PostgreSQL. Unlike PostgreSQL, which relies on disk-based storage and vertical scaling, Redis operates primarily in memory, significantly reducing read and write latency. Additionally, Redis’s distributed architecture enables horizontal scaling, making it an ideal fit for high-throughput messaging in P2P communication scenarios. - -![TBMQ peer-to-peer benchmark with 600,000 MQTT connections on Redis](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-600k-Redis-V1.svg) - -With these benefits in mind, we started our migration process with an evaluation of data structures that could preserve the functionality of the PostgreSQL approach while aligning with Redis Cluster constraints to enable efficient horizontal scaling. This also presented an opportunity to improve certain aspects of the original design, such as periodic cleanups, by leveraging Redis features like built-in expiration mechanisms. - -### Redis cluster constraints - -When migrating from PostgreSQL to Redis, we recognized that replicating the existing data model would require multiple Redis data structures to efficiently handle message persistence and ordering. This, in turn, meant using multiple keys for each persistent MQTT Client session. - -![Redis cluster architecture supporting TBMQ at scale](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/redis-cluster.png) - -Redis Cluster distributes data across multiple slots to enable horizontal scaling. However, multi-key operations must access keys within the same slot. If the keys reside in different slots, the operation triggers a cross-slot error, preventing the command from executing. We used the persistent MQTT client ID as a [hash tag](https://redis.io/docs/latest/operate/oss_and_stack/reference/cluster-spec/#hash-tags) in our key names to address this. By enclosing the client ID in curly braces `{}`, Redis ensures that all keys for the same client are hashed to the same slot. This guarantees that related data for each client stays together, allowing multi-key operations to proceed without errors. - -### Atomic operations via Lua scripts - -Consistency is critical in a high-throughput environment like TBMQ, where many messages can arrive simultaneously for the same MQTT client. Hashtagging helps to avoid cross-slot errors, but without atomic operations, there is a risk of race conditions or partial updates. This could lead to message loss or incorrect ordering. It is important to make sure that operations updating the keys for the same MQTT client are atomic. - -![Lua scripting in Redis for atomic operations in TBMQ broker](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/atomicity_with_lua_scripting_2x.webp) - -Redis is designed to execute individual commands atomically. However, in our case, we need to update multiple data structures as part of a single operation for each MQTT client. Executing these sequentially without atomicity opens the door to inconsistencies if another process modifies the same data in between commands. That’s where [Lua scripting](https://redis.io/docs/latest/develop/interact/programmability/eval-intro/) comes in. Lua script executes as a single, isolated unit. During script execution, no other commands can run concurrently, ensuring that the operations inside the script happen atomically. - -Based on this information, we decided that for any operation, such as saving messages or retrieving undelivered messages upon reconnection, we will execute a separate Lua script. This ensures that all operations within a single Lua script reside in the same hash slot, maintaining atomicity and consistency. - -### Choosing the right Redis data structures - -One of the key requirements of the migration was maintaining message order, a task previously handled by the `serial_number` column in PostgreSQL’s `device_publish_msg` table. After evaluating various Redis data structures, we determined that [sorted sets](https://redis.io/docs/latest/develop/data-types/sorted-sets/) (ZSETs) were the ideal replacement. - -Redis sorted sets naturally organize data by score, enabling quick retrieval of messages in ascending or descending order. While sorted sets provided an efficient way to maintain message order, storing full message payloads directly in sorted sets led to excessive memory usage. Redis does not support per-member TTL within sorted sets. As a result, messages persisted indefinitely unless explicitly removed. Similar to PostgreSQL, we had to perform periodic cleanups using `ZREMRANGEBYSCORE` to delete expired messages. This operation carries a complexity of `O(log N + M)`, where `M` is the number of elements removed. To overcome this limitation we decided to store message payloads using [strings](https://redis.io/docs/latest/develop/data-types/strings/) data structure while storing in the sorted set references to these keys. - -![TBMQ benchmark results comparison table](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/table-1.webp) -*client_id is a placeholder for the actual client ID, while the curly braces \{\} around it are added to create a hash tag.* - -In the image above, you can see that the score continues to grow even when the MQTT packet ID wraps around. Let’s take a closer look at the details illustrated in this image. At first, the reference for the message with the MQTT packet ID equal to `65534` was added to the sorted set: - -``` -ZADD {client_id}_messages 65534 {client_id}_messages_65534 -``` - -Here, `{client_id}_messages` is the sorted set key name, where `{client_id}` acts as a hash tag derived from the persistent MQTT client’s unique ID. The suffix `_messages` is a constant added to each sorted set key name for consistency. Following the sorted set key name, the score value `65534` corresponds to the MQTT packet ID of the message received by the client. Finally, we see the reference key that points to the actual payload of the MQTT message. Similar to the sorted set key, the message reference key uses the MQTT client’s ID as a hash tag, followed by the `_messages` suffix and the MQTT packet ID value. - -In the next iteration, we add the message reference for the MQTT message with a packet ID equal to `65535` into the sorted set. This is the maximum packet ID, as the range is limited to `65535`. - -``` -ZADD {client_id}_messages 65535 {client_id}_messages_65535 -``` - -So at the next iteration MQTT packet ID should be equal to `1`, while the score should continue to grow and be equal to `65536`. - -``` -ZADD {client_id}_messages 65536 {client_id}_messages_1 -``` - -This approach ensures that the message’s references will be properly ordered in the sorted set regardless of the packet ID’s limited range. - -Message payloads are stored as string values with `SET` commands that support expiration (`EX`), providing `O(1)` complexity for writes and `TTL` applications: - -```css -SET {client_id}_messages_1 "{ - \"packetType\":\"PUBLISH\", - \"payload\":\"eyJkYXRhIjoidGJtcWlzYXdlc29tZSJ9\", - \"time\":1736333110026, - \"clientId\":\"client\", - \"retained\":false, - \"packetId\":1, - \"topicName\":\"europe/ua/kyiv/client/0\", - \"qos\":1 -}" EX 600 -``` - -Another benefit aside from efficient updates and TTL applications is that the message payloads can be retrieved: - -``` -GET {client_id}_messages_1 -``` - -or removed: - -``` -DEL {client_id}_messages_1 -``` - -with constant complexity `O(1)` without affecting the sorted set structure. - -Another very important element of our Redis architecture is the use of a string key to store the last MQTT packet ID processed: - -``` -GET {client_id}_last_packet_id -"1" -``` - -This approach serves the same purpose as in the PostgreSQL solution. When a client reconnects, the server must determine the correct packet ID to assign to the next message that will be saved in Redis. Initially, we considered using the sorted set’s highest score as a reference. However, since there are scenarios where the sorted set could be empty or completely removed, we concluded that the most reliable solution is to store the last packet ID separately. - -#### Managing sorted set size dynamically - -This hybrid approach, leveraging sorted sets and string data structures, eliminates the need for periodic cleanups based on time, as per-message TTLs are now applied. In addition, following the PostgreSQL design we needed to address somehow the cleanup of the sorted set based on the messages limit set in the configuration. - -```css -# Maximum number of PUBLISH messages stored for each persisted DEVICE client -limit: "${MQTT_PERSISTENT_SESSION_DEVICE_PERSISTED_MESSAGES_LIMIT:10000}" -``` - -This limit is an important part of our design, allowing us to control and predict the memory allocation required for each persistent MQTT client. For example, a client might connect, triggering the registration of a persistent session, and then rapidly disconnect. In such scenarios, it is essential to ensure that the number of messages stored for the client (while waiting for a potential reconnection) remains within the defined limit, preventing unbounded memory usage. - -``` -if (messagesLimit > 0xffff) { - throw new IllegalArgumentException("Persisted messages limit can't be greater than 65535!"); -} -``` - -To reflect the natural constraints of the MQTT protocol, the maximum number of persisted messages for individual clients is set to `65535`. - -To handle this within the Redis solution, we implemented dynamic management of the sorted set’s size. When new messages are added, the sorted set is trimmed to ensure the total number of messages remains within the desired limit, and the associated strings are also cleaned up to free up memory. - -``` --- Get the number of elements to be removed -local numElementsToRemove = redis.call('ZCARD', messagesKey) - maxMessagesSize --- Check if trimming is needed -if numElementsToRemove > 0 then - -- Get the elements to be removed (oldest ones) - local trimmedElements = redis.call('ZRANGE', messagesKey, 0, numElementsToRemove - 1) - -- Iterate over the elements and remove them - for _, key in ipairs(trimmedElements) do - -- Remove the message from the string data structure - redis.call('DEL', key) - -- Remove the message reference from the sorted set - redis.call('ZREM', messagesKey, key) - end -end -``` - -#### Message retrieval and cleanup - -Our design not only ensures dynamic size management during the persistence of new messages but also supports cleanup during message retrieval, which occurs when a device reconnects to process undelivered messages. This approach keeps the sorted set clean by removing references to expired messages. - -``` --- Define the sorted set key -local messagesKey = KEYS[1] --- Define the maximum allowed number of messages -local maxMessagesSize = tonumber(ARGV[1]) --- Get all elements from the sorted set -local elements = redis.call('ZRANGE', messagesKey, 0, -1) --- Initialize a table to store retrieved messages -local messages = {} --- Iterate over each element in the sorted set -for _, key in ipairs(elements) do - -- Check if the message key still exists in Redis - if redis.call('EXISTS', key) == 1 then - -- Retrieve the message value from Redis - local msgJson = redis.call('GET', key) - -- Store the retrieved message in the result table - table.insert(messages, msgJson) - else - -- Remove the reference from the sorted set if the key does not exist - redis.call('ZREM', messagesKey, key) - end -end --- Return the retrieved messages -return messages -``` - -By leveraging Redis’ sorted sets and strings, along with Lua scripting for atomic operations, our new design achieves efficient message persistence and retrieval, as well as dynamic cleanup. This design addresses the scalability limitations of the PostgreSQL-based solution. - -In the next sections, we describe the performance of the new Redis-based architecture compared to the PostgreSQL solution. These sections present the results of the performance tests and their key findings. - -## Migration from Jedis to Lettuce - -![Migration diagram from Jedis to Lettuce Redis client in TBMQ](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/migration_from_jedis_to_lettuce.webp) - -As we mentioned earlier, we conducted a prototype test that revealed the limit of 30k msg/s throughput when using PostgreSQL for persistence message storage. At the moment we migrated to Redis, we already used the [Jedis](https://github.com/redis/jedis) library for Redis interactions, primarily for cache management, and extended it to handle message persistence for persistent MQTT clients. However, the initial results of the Redis implementation with Jedis were unexpected. While we anticipated Redis would significantly outperform PostgreSQL, the performance improvement was modest – reaching only 40k msg/s throughput compared to the 30k msg/s limit with PostgreSQL. - -![TBMQ performance benchmark results dashboard](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/screenshot_from_2025_01_03_16_37_17_1x.webp) -*RedisInsight shows ~66k commands/s per node, aligning with TBMQ’s 40k msg/s, as Lua scripts trigger multiple Redis operations per message.* - -This led us to investigate the bottlenecks, where we discovered that Jedis was a limiting factor. While reliable, Jedis operates synchronously, processing each Redis command sequentially. This forces the system to wait for one operation to complete before executing the next. In high-throughput environments, this approach significantly limited Redis’s potential, preventing the full utilization of system resources. - -To overcome this limitation, we migrated to [Lettuce](https://github.com/redis/lettuce), an asynchronous Redis client built on top of [Netty](https://github.com/netty/netty). With Lettuce, our throughput increased to 60k msg/s, demonstrating the benefits of non-blocking operations and improved parallelism. - -![TBMQ broker monitoring metrics screenshot](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/screenshot_from_2025_01_03_16_45_49_1x.webp) -*At 60k msg/s, RedisInsight shows ~100k commands/s per node, aligning with the expected increase from 40k msg/s, which produced ~66k commands/s per node.* - -Lettuce allows multiple commands to be sent and processed in parallel, fully exploiting Redis’s capacity for concurrent workloads. Ultimately, the migration unlocked the performance gains we expected from Redis, paving the way for successful P2P testing at scale. - -## Scaling point-to-point messaging - -With Redis and Lettuce fully integrated, the next challenge was ensuring TBMQ’s ability to handle large-scale P2P messaging in a distributed environment. To simulate real-world conditions, we deployed [TBMQ on AWS EKS (Elastic Kubernetes Service)](https://tbmq.io/docs/installation/cluster/aws-cluster-setup/), allowing us to dynamically scale and stress-test the system. - -To evaluate performance and prove that our system can scale efficiently, we started with 200,000 messages per second and increased the load by 200,000 messages in each iteration. In each phase, we scaled the number of TBMQ brokers and Redis nodes to handle the growing traffic while keeping the system stable. For the 1M msg/sec test, we also scaled the number of Kafka brokers to handle the corresponding workload. - -| Throughput (msg/sec) | Publishers | Subscribers | TBMQ brokers | Redis Nodes | Kafka brokers | -| --- | --- | --- | --- | --- | --- | -| 200k | 100k | 100k | 1 | 3 | 3 | -| 400k | 200k | 200k | 2 | 5 | 3 | -| 600k | 300k | 300k | 3 | 7 | 3 | -| 800k | 400k | 400k | 4 | 9 | 3 | -| 1M | 500k | 500k | 5 | 11 | 5 | - -Beyond adding resources, each increase in load required fine-tuning of Kafka topic partitioning and Lettuce command batching parameters. These adjustments helped distribute traffic evenly and keep latency stable, preventing bottlenecks as we scaled. - -| Throughput (msg/sec) | Kafka topic partitions | Lettuce batch size | -| --- | --- | --- | -| 200k | 12 | 150 | -| 400k | 12 | 250 | -| 600k | 12 | 300 | -| 800k | 16 | 400 | -| 1M | 20 | 500 | - -We reached our target of **1 million messages per second**, validating TBMQ’s capability to support high-throughput reliable P2P messaging. To better illustrate the test setup and results, the following diagram provides a visual breakdown of the final performance test. - -![TBMQ peer-to-peer test reaching 1 million MQTT connections with Redis](/images/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/P2P-1M-Redis-V2.svg) - -**Tests results** - -Throughout testing, we monitored key performance indicators such as CPU utilization, memory usage, and message processing latency. One of TBMQ’s standout advantages, highlighted in our P2P testing, is its exceptional messages-per-second per CPU core performance. Compared to public benchmarks of other brokers, TBMQ consistently delivers higher throughput with fewer resources, reinforcing its efficiency in large-scale deployments. - -**Key takeaways from tests include:** - -- **Scalability:** TBMQ demonstrated linear scalability. By incrementally adding TBMQ nodes, Redis nodes, and Kafka nodes at higher workloads, we maintained reliable performance as the message throughput increased from 200k to 1M msg/sec. -- **Efficient Resource Utilization:** CPU utilization on TBMQ nodes remained consistently around ~90% across all test phases, indicating that the system effectively used available resources without overconsumption. -- **Latency Management:** The observed latency across all tests remained within two-digit bounds. This was predictable given the QoS 1 level chosen for our test, applied to both publishers and persistent subscribers. We also tracked the average acknowledgment latency for publishers, which stayed within single-digit bounds across all test phases. -- **High Performance:** TBMQ’s one-to-one communication pattern showed excellent efficiency, processing about 8900 msg/s per CPU core. We calculated this by dividing the total throughput by the total number of CPU cores used in the setup. - -Additionally, the following table provide a comprehensive summary of the key elements and results of the final 1M msg/sec test: - -| QoS | P2P latency | Publishlatency | Messages per second per CPU core | TBMQ CPU usage | Payload(bytes) | -| --- | --- | --- | --- | --- | --- | -| 1 | ~75ms | ~8ms | 8900 | 91% | 62 | - -For a deeper dive into the testing architecture, methodology, and results, check out our [detailed performance testing article](https://tbmq.io/docs/reference/1m-throughput-p2p-performance-test/). - -## Conclusion - -[TBMQ 2.x](https://tbmq.io/docs/releases/#v201-december-31-2024) sets a new benchmark for self-hosted MQTT brokers, proving its ability to handle one million messages per second for persistent sessions without data loss—even in the event of hardware failures. Designed to eliminate single points of failure and bottlenecks, TBMQ achieves exceptional efficiency through a combination of Redis for persistence, Kafka for message distribution, and a highly optimized broker codebase. - -In our tests and by comparing public data from other platforms, TBMQ leads in messages processed per CPU core (**~8,900 msg/sec**), making it a strong choice for high-throughput IIoT and other MQTT deployments. This efficiency is not just a raw metric—it also means lower infrastructure costs and simpler scaling. - -TBMQ has long been a top performer in fan-in and fan-out scenarios, handling data from millions of devices to back-end systems with ease. Now, it also stands out in P2P messaging, offering low latency and high throughput for one-to-one communication use cases. If you need massive throughput, low latency, and efficient resource usage, TBMQ offers a proven path forward. diff --git a/src/content/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs.mdx b/src/content/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs.mdx deleted file mode 100644 index e40f99c44e..0000000000 --- a/src/content/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs.mdx +++ /dev/null @@ -1,158 +0,0 @@ ---- -title: 'Introducing TBMQ Professional Edition: The MQTT Broker for Enterprise Needs' -description: 'TBMQ Professional Edition launches with enterprise-grade security, observability, integration, and support — built on the TBMQ open-source core.' -date: 2026-01-20 -updatedDate: 2026-01-19 -author: dlandiak -categories: ['tech', 'updates'] -featuredImage: '/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/cover.webp' -featuredImageAlt: 'Introducing TBMQ Professional Edition' -draft: false ---- -import BlogCTA from '~/components/Blog/BlogCTA.astro'; - -We're excited to introduce [TBMQ Professional Edition](https://tbmq.io/docs/pe/) (TBMQ PE) – the next step in the evolution of our MQTT broker. TBMQ PE is built on top of [TBMQ's](https://tbmq.io/) proven, production-ready core and adds advanced features for security, observability, integration, and professional support. Starting with this release, the existing open-source version will be known as [TBMQ Community Edition](https://tbmq.io/docs/) (TBMQ CE). - -TBMQ CE remains fully open-source and actively maintained. For existing users, TBMQ PE will feel immediately familiar, extending the platform with enterprise-focused capabilities and operational tooling designed to meet higher reliability and compliance requirements – without changing the core behavior you already trust. - -## TBMQ CE vs TBMQ PE: Which edition is right for you? - -Here's how the two editions align in terms of core features, security, extensibility, and support. See the [full comparison table](https://tbmq.io/#comparison-features). - -![TBMQ Community Edition vs Professional Edition feature comparison](/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/ce_pe-1.webp) - - - -When we built TBMQ CE, our goal was simple: create the most reliable and performant open-source MQTT broker possible. We engineered the core for long-term durability, high throughput, and scalability – fully expecting that many of you would deploy it in demanding, production-critical environments where reliability cannot be compromised. - -As TBMQ adoption accelerated, we saw a clear pattern: organizations were using TBMQ at scales and in operational contexts that required more than what an open-source edition should provide on its own. Teams needed stronger security controls, deeper operational insight, advanced integrations, and guaranteed support. These needs didn't come from theory – they came directly from real deployments, real customers, and real production requirements. - -TBMQ Professional Edition is our response to those needs. It provides a dedicated, enterprise-focused offering designed to support mission-critical workloads and ensure the sustainable development of advanced features, operational tooling, and service-level guarantees. - -Both editions share the same battle-tested core – delivering the performance, scalability, fault-tolerance, and full MQTT 3.x/5.0 feature set that TBMQ is known for. - -**TBMQ Community Edition (CE)** remains fully open-source, production-ready, and actively maintained. It is ideal for teams whose operational, security, and compliance needs are straightforward and who prefer the freedom of an open-source deployment. - -**TBMQ Professional Edition (PE)** builds on the CE core with capabilities designed specifically for complex or regulated environments, including: - -- **Stronger Security Options** – Enhanced controls supporting higher compliance and governance requirements. -- **Deeper Visibility** – Advanced monitoring, metrics, and dashboards for complete operational insight. -- **Extended Integrations** – Ready-made connectors that streamline adoption inside enterprise ecosystems. -- **Professional Support** – Direct access to the TBMQ team with guaranteed response times and optional SLAs. - -CE is the best way to start and run many workloads; PE is for teams that need extra visibility, security, and guarantees on top of the same proven core. - -## What you get with TBMQ Professional Edition - -TBMQ PE launches with the following features, and many more are already on the roadmap for upcoming releases. - -### Single sign-on (SSO) - -As MQTT usage grows across teams and environments, managing separate user accounts becomes difficult and time-consuming. TBMQ Professional Edition solves this by introducing **Single Sign-On (SSO)**, allowing you to connect TBMQ to your existing identity provider through **OAuth 2.0 and OpenID Connect (OIDC)**. - -![Single sign-on authentication in TBMQ Professional Edition](/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/sso.webp) - -With SSO enabled, administrators no longer need to create or maintain local TBMQ accounts. Users authenticate using the same corporate identity they rely on for other internal systems, making onboarding simpler and access management more consistent across the organization. - -SSO also strengthens security by inheriting the authentication policies and controls defined by your identity provider. This ensures that TBMQ aligns with your organization's established identity standards without adding separate account management overhead. - -For teams using centralized identity management, SSO integrates TBMQ seamlessly into existing workflows and significantly streamlines day-to-day administration. - -Check out our [Single Sign-On (SSO) / OAuth2](https://tbmq.io/docs/pe/security/oauth-2-support/) guide. - -### Role-based access control (RBAC) - -As organizations grow, not every team member needs full administrative access to the MQTT broker. TBMQ Professional Edition introduces **Role-Based Access Control (RBAC)** to bring structure, safety, and clarity to user permissions. With RBAC, administrators can assign predefined roles that determine what a user is allowed to see or do inside TBMQ. - -![Role-based access control in TBMQ Professional Edition](/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/rbac.webp) - -TBMQ PE includes two built-in roles: - -- **Admin** – Full access to all broker configuration and operational capabilities. -- **Viewer** – Read-only access to broker data, metrics, and client activity, without the ability to modify settings or perform administrative actions. - -RBAC helps ensure that users have only the level of access appropriate for their responsibilities. It improves security by limiting sensitive operations to authorized personnel, simplifies user management by avoiding granular permission setups, and supports compliance requirements through clear separation of duties. - -Typical usage is straightforward: grant **Admin** access to team members responsible for maintaining or configuring the broker, and assign **Viewer** access to operations, support, or monitoring teams who need visibility without the risk of accidental changes. - -Check out our [RBAC](https://tbmq.io/docs/pe/security/rbac/) guide. - -### White Labeling - -TBMQ Professional Edition includes **White Labeling**, allowing you to adapt the TBMQ UI to your brand or product identity. This is especially valuable for companies delivering IoT platforms or customer-facing solutions where visual consistency matters. - -![White-label branding options in TBMQ Professional Edition](/images/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/white_labeling-1.webp) - -You can easily customize the interface by setting a branded application title, uploading your logo, adjusting its size, and replacing the default favicon. TBMQ PE also lets you define your own **primary** and **accent** color palettes, giving the UI a look and feel that matches your design guidelines. - -For deeper customization, the **Advanced CSS** option allows full control over UI elements – icons, backgrounds, fonts, buttons, scrollbars, and more – enabling highly personalized themes. - -The **Login** page can also be branded with your domain, custom visuals, and colors, ensuring a unified experience from the very first interaction. - -White labeling in TBMQ PE makes it simple to create a polished and consistent interface tailored to your organization or your customers. - -Check out our[ ](https://tbmq.io/docs/pe/security/rbac/)[White labeling](https://tbmq.io/docs/pe/white-labeling/) guide. - - - -### Roadmap - -The first release of TBMQ Professional Edition is only the beginning. We're actively expanding PE with new capabilities that strengthen security, observability, and integration with existing enterprise systems. Upcoming releases will focus on: - -- **Additional system integrations** beyond the current HTTP, MQTT, and Kafka options available in CE -- **Audit logs** for tracking user activity and configuration changes -- **Expanded security features** for tighter access control and operational safety -- **Advanced monitoring**, including deeper visibility into message flow, client behavior, and system performance - -## Licensing, support, and how to get it - -TBMQ Professional Edition is available through both **Self-managed Subscription** and **Perpetual License** models, offering organizations total flexibility in how they budget and operate their infrastructure. Instead of fixed tiers, we offer a transparent, consumption-based calculator that lets you pay only for the exact capacity you need. - -You can customize your license by selecting: - -- **The exact number of Sessions and Throughput (msg/sec)** required for your workload. -- **The number of Production and Development instances** to support your High Availability (HA) and CI/CD requirements. -- **Optional Add-ons**, such as White Labeling for custom corporate branding. - -Getting started is seamless: configure your requirements on the [TBMQ pricing page](/pricing/?section=tbmq-options&product=tbmq-pe), then proceed to the ThingsBoard Licensing Server to activate your license. If you do not have an account, the system will guide you through the creation process during activation. - -### Expert support tailored to your scale - -Our support model scales alongside your deployment. Support levels are automatically determined by your configuration: - -- **Community Support:** Standard for configurations with a total monthly value under $300. -- **Direct Help Desk:** Included for all configurations exceeding $300 per month. -- **Priority Help Desk:** Available as a dedicated add-on for organizations requiring prioritized response times and direct access to our expert support queue. - -Users with Help Desk access are integrated into the ThingsBoard Support Portal. Our team provides expert assistance with installation, migration using recommended deployment methods, configuration optimization, and troubleshooting of out-of-the-box features. For organizations with the most demanding operational requirements, optional 24/7 support SLAs are also available as part of our managed services. - -This modular licensing and support structure ensures that whether you are a startup or a global enterprise, you can deploy TBMQ PE with total confidence in your production environment. - -Ready to explore licensing options? - -Visit the TBMQ pricing page to configure your license. Use our interactive calculator to select the exact sessions, throughput, and instances you need to fit your specific deployment requirements. - -View Pricing & Licensing - -## Final words - -The launch of TBMQ Professional Edition marks an important milestone in the evolution of our MQTT platform. - -Whether you're building your first MQTT-based solution or operating mission-critical infrastructure at scale, TBMQ provides a solid, high-performance foundation – with the option to go further through enhanced security, observability, customization, and professional support. - -To explore TBMQ PE, review the available licensing options, and activate your license through the ThingsBoard Licensing Server. We're excited to see what you build with the new capabilities and look forward to continuing this journey together. - -If this sounds like the direction your MQTT infrastructure is heading, **get in touch and let's see how TBMQ PE can fit into your stack.** diff --git a/src/content/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more.mdx b/src/content/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more.mdx deleted file mode 100644 index e34e60d255..0000000000 --- a/src/content/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 'TBMQ 1.3.0 release: WebSocket client, advanced MQTT 5 features, and more' -description: 'Thingsboard releases TBMQ 1.3.0.This update improves MQTT over WebSocket functionality by introducing a new WebSocket client.' -date: 2024-04-02 -updatedDate: 2024-09-03 -author: dlandiak -categories: ['updates'] -featuredImage: '/images/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more/cover.webp' -featuredImageAlt: 'TBMQ 1.3.0 release' -draft: false ---- - -We’re delighted to introduce TBMQ version 1.3.0! This update improves MQTT over WebSocket functionality by introducing a new WebSocket client. It also broadens the scope of supported MQTT 5 features. Here’s an overview of the features and updates included in this release. - -## WebSocket Client - -We have added the new WebSocket client – a browser-accessible tool that greatly simplifies the debugging and testing of MQTT clients across various scenarios. Utilizing the [MQTT over WebSocket ](https://tbmq.io/docs/user-guide/mqtt-over-ws/)feature, this tool offers a user-friendly interface for a range of functionalities. Key features include: - -- **Multiple connections**: Effortlessly manage several MQTT client connections at once. -- **Advanced connection settings and authentication**: Customize your connection parameters with a range of sophisticated options, catering to diverse requirements. Select from multiple authentication options to ensure a user-friendly and secure connection experience. -- **Subscription management**: Quickly add or change what topics you’re subscribed to allowing you to specify advanced MQTT options. -- **Messages and logging**: Keep track of message flows and connection status logs for effective debugging and analysis. -- **Message publishing**: Conveniently publish messages with the ability to customize various MQTT-related settings for tailored communication. - -## MQTT 5: Flow Control - -This update contains the Flow Control feature, a crucial enhancement for managing the rate of message flow in MQTT communications. This feature is particularly important in scenarios where clients or brokers have limited processing capabilities or bandwidth. - -**How It Works:** Flow Control in MQTT 5 is achieved through a key parameter: Receive Maximum. It dictates the maximum number of QoS 1 and QoS 2 messages that the client or broker is willing to process concurrently. Receive Maximum is exchanged within the CONNECT and CONNACK packets. Its default value is 65,535 based on the MQTT specification. - -**Why It’s Needed:** Flow Control is an essential mechanism for several reasons: - -- **Preventing overload:** Without Flow Control, there’s a risk of overwhelming a client or broker with more messages than it can process. This can lead to system lags, or in worst-case scenarios, cause crashes or unresponsiveness, particularly in smaller, less powerful devices. -- **Ensuring reliable communication:** By controlling the flow of messages, MQTT ensures that data transmission remains stable and reliable. -- **Optimizing resource use:** Flow Control allows for the efficient use of system resources. It ensures that devices are not bogged down by unnecessary processing tasks, which is particularly important in systems with limited computational power. - -**Use Case**: It can be any scenario (e.g. a smart home system or a traffic management system) where devices are constrained by processing power and cannot handle transmitting or receiving large amounts of data efficiently. - -## MQTT 5: Request-response pattern - -The MQTT 5 Request-Response pattern introduces a structured approach to communication, enabling devices to send requests and receive responses in a reliable and efficient manner. - -**How It Works:** In the Request-Response pattern, a client sends a request message to a specific topic, typically indicating the action it wants to perform. This request includes essential parameters such as the Response Topic and Correlation Data. The recipient, which may be another client or application, processes the request and issues a corresponding response message directed to the specified Response Topic. This response provides the result or acknowledgment of the request. Utilizing Correlation Data, the original requester can precisely match the received response to its corresponding request, ensuring seamless bidirectional communication. - -**Why It’s Needed:** The Request-Response pattern addresses the need for synchronous communication in IoT systems, where devices often require immediate feedback or confirmation for their actions. By establishing a structured request-response flow, MQTT 5 ensures a reliable and timely exchange of information between devices and applications. - -**Use Case:** Consider a home automation scenario where a user wants to remotely control their smart lights. The user sends a request message to the TBMQ, specifying the action to turn on the lights. The broker transmits the request to the receiver which executes the action and sends the response message back to the user, confirming that the lights have been successfully turned on. This bidirectional communication allows for seamless interaction between the user and the smart home system, enhancing the overall user experience. - -## Other notable enhancements - -In addition to the features highlighted earlier, this release includes several points that strengthen the system’s reliability and efficiency. - -Significant enhancements have been made in backpressure management specifically for non-persistent subscribers. This improvement allows the system to handle data flow surges for these subscribers more efficiently by implementing rate limits. As a result, it ensures the system’s stability, maintaining consistent performance even under conditions of high demand. - -The enhancement of the disconnect client command with Reason Codes marks a notable improvement, offering clearer insights into disconnection causes (e.g. “Session taken over”, “Administrative action”) and facilitating more targeted troubleshooting and analysis. - -This version brings improvements in memory usage and overall performance. An important resolution of a direct memory leak issue leads to an optimized operational environment. This results in reduced latency and higher throughput, significantly boosting the system’s performance and robustness. diff --git a/src/content/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more.mdx b/src/content/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more.mdx deleted file mode 100644 index 18e73b9090..0000000000 --- a/src/content/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: 'TBMQ 2.0: migration to Redis, MQTT 5.0 support, and more' -description: 'TBMQ 2.0 release: persistent device sessions migrated from PostgreSQL to Redis, full MQTT 5.0 support, and other architecture improvements.' -date: 2024-11-05 -updatedDate: 2024-11-05 -author: dlandiak -categories: ['updates'] -featuredImage: '/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/cover.webp' -featuredImageAlt: 'TBMQ 2.0' -draft: false ---- - -We’re delighted to introduce TBMQ version 2.0.0! This release brings a major update with data migration of [persistent sessions for devices](https://tbmq.io/docs/architecture/#persistent-device-client) from PostgreSQL to Redis. It also expands TBMQ’s MQTT 5.0 feature set, achieving full compatibility with the MQTT 5.0 standard. Here’s an overview of the features and updates included in this release. - -## Migration from PostgreSQL to Redis - -![TBMQ 2.0 MQTT 5.0 protocol support feature](/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-4.webp) - -With this release, we’ve made a strategic shift from PostgreSQL to Redis specifically for handling data related to **persistent sessions for devices**. This migration is a core part of our commitment to optimizing performance and scalability in high-demand MQTT environments where managing persistent client sessions efficiently is crucial. - -### Why the change? - -While PostgreSQL is a powerful relational database, it wasn’t designed to handle the high-throughput, low-latency requirements of MQTT brokers. Our experience showed that as data volume and request rates increased, PostgreSQL struggled to maintain the speed and responsiveness essential for real-time MQTT workloads due to its lack of horizontal scalability options. - -### What Redis brings to the table - -Redis, a fast, in-memory data store, is built for speed, supporting high-performance operations with minimal latency. By migrating to Redis, we now achieve: - -- **Improved data access speed**: Redis allows us to store key MQTT data in memory, drastically reducing retrieval times compared to disk-based systems. -- **Enhanced scalability**: Redis’s efficient handling of high-frequency read/write operations aligns perfectly with the needs of MQTT brokers, enabling TBMQ to scale horizontally and easily manage millions of concurrent connections. -- **Low-latency operations**: Redis’s non-blocking I/O and simple data structures mean that even under heavy load, response times remain low, ensuring smoother message processing and session management. - -### What’s next? - -This migration is only the beginning. Our engineering team is dedicated to leveraging Redis to its fullest potential, and we’re already working on additional performance optimizations. Stay tuned for more detailed performance test results as we push the boundaries of what TBMQ can achieve in real-time MQTT processing. - -## Advanced session metrics - -![TBMQ 2.0 administration interface preview](/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-6-2.webp) - -With the new client session metrics in TBMQ, administrators gain a detailed view of each client’s messaging patterns, broken down by Quality of Service (QoS) levels. These metrics offer several key advantages for managing and optimizing the MQTT broker environment: - -1. **Enhanced session visibility**: By seeing how many messages are processed at each QoS level, administrators can identify patterns in client usage and detect anomalies, such as unusually high or low message counts, which may indicate connection issues or performance bottlenecks. -2. **Proactive troubleshooting**: With detailed metrics, issues such as message loss, delayed delivery, or irregular publish rates can be pinpointed and investigated early, minimizing potential disruptions. -3. **Client behavior analysis**: Advanced metrics offer granular insights into individual client behavior, helping administrators identify top publishers and subscribers. - -Overall, this feature transforms the monitoring experience, making it easier to ensure the broker remains performant and reliable, even as client numbers and message volumes scale. - -## Unauthorized clients - -![Unauthorized clients monitoring in TBMQ 2.0](/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/unauthoraized-clients.webp) - -To bolster security, TBMQ now includes an ‘Unauthorized Clients’ feature, which provides real-time monitoring of connection attempts made by clients with invalid credentials. This feature logs details such as the client ID, IP address, username, authentication method, and the specific reason for failure, offering administrators a clear view of unauthorized access attempts. - -By tracking these failed connections, administrators gain valuable insights into potential security threats, including repeated access attempts from certain IPs or specific usernames, enabling them to take proactive security measures. The Unauthorized Clients feature is essential for maintaining a secure and robust broker environment, especially in deployments where client authentication integrity is critical. - -## Subscriptions - -![Active subscriptions overview in TBMQ 2.0](/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/subscriptions.webp) - -TBMQ’s new Subscriptions page offers a centralized view that brings clarity and control to broker monitoring by displaying all active subscriptions in one accessible location. With a single click, administrators can open a client’s session details directly from this page, making it easy to add, edit, or delete subscriptions on the spot. - -This comprehensive overview streamlines subscription management, helping administrators track which clients are subscribed to specific topics, assess subscription distribution across QoS levels, and quickly make adjustments as needed. By simplifying these processes, the Subscriptions page is instrumental in managing broker activity, diagnosing subscription issues, and ensuring clients connect to the right topics efficiently. - -## MQTT 5.0: Subscription identifier - -![TBMQ 2.0 release overview with new features](/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-02.webp) - -This update introduces the Subscription Identifier feature, an important addition to optimizing message tracking and processing in MQTT communications. - -**How It Works:** The Subscription Identifier in MQTT 5.0 allows the client to assign a unique identifier to each subscription. When the broker sends messages that match a subscription, it includes this identifier in the message properties, allowing the client to recognize which subscription triggered the message. The Subscription Identifier is set when the client subscribes to a topic, and it remains associated with that subscription until it is modified or removed. - -**Why It’s Needed: **The Subscription Identifier is essential for several reasons: - -- **Efficient message routing**: By tagging each message with a Subscription Identifier, clients can quickly determine the origin subscription, making it easier to handle and route messages appropriately. -- **Improved performance in message processing**: Subscription Identifiers allow clients to reduce the need for complex message parsing, which is especially important in high-throughput environments where rapid response times are critical. -- **Enhanced analytics**: The feature allows clients to analyze message flow on a per-subscription basis, providing deeper insights into traffic patterns and helping optimize the configuration for various use cases. - -**Use Case:** The Subscription Identifier is particularly useful in scenarios with multiple subscriptions and diverse message flows, such as IoT applications with numerous sensors and devices. For example, in a smart city infrastructure, each subscription (e.g., traffic data, weather data, air quality monitoring) can be uniquely identified, allowing the central system to efficiently process and route data to the appropriate services for further action. - -## MQTT 5.0: Enhanced authentication - -![TBMQ 2.0 architecture migration to Redis](/images/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/TBMQ-1.webp) - -This update includes the Enhanced Authentication feature, a significant improvement to the MQTT protocol that allows for more flexible and secure client authentication methods. - -**How It Works:** Enhanced Authentication in MQTT 5.0 introduces a new AUTH packet, which enables multi-step authentication processes. This allows the broker and client to exchange multiple authentication-related messages during a session, supporting advanced authentication schemes such as challenge-response mechanisms and token-based authentication. The authentication process can occur at any time during the session, allowing for re-authentication as needed. - -**Why It’s Needed: **Enhanced Authentication is essential for several reasons: - -- **Greater security flexibility**: Traditional MQTT authentication typically relies on a single-step username and password exchange, which can be limiting for applications with stringent security needs. Enhanced Authentication enables the use of more sophisticated methods, such as SCRAM (Salted Challenge Response Authentication Mechanism), which provides secure, challenge-based authentication. SCRAM is particularly valuable for securing data exchanges by preventing password exposure during transmission and mitigating certain attack vectors, such as replay attacks. -- **Support for dynamic authentication mechanisms**: Enhanced Authentication allows for re-authentication during an ongoing session. This feature is particularly valuable for applications that need to validate client credentials periodically or handle token expiration gracefully, ensuring continuous and secure access. -- **Adaptability to industry-specific security standards**: Many industries, such as finance and healthcare, have stringent authentication standards. Enhanced Authentication provides the flexibility to meet these standards, allowing businesses to adopt MQTT while complying with industry regulations. - -**Use Case:** Enhanced Authentication is particularly beneficial for IoT deployments in sectors requiring strong security, such as industrial automation and healthcare. For example, in a healthcare setting, devices transmitting sensitive patient data can use token-based authentication to ensure secure, periodic revalidation, protecting against unauthorized access and meeting strict compliance requirements. - -## Other notable features and enhancements - -In addition to the features highlighted earlier, we’ve made significant improvements to enhance user insights, overall system robustness, and performance. - -The client session details now include **MQTT client credentials** and **MQTT version** information for authenticated clients. This enhancement provides better visibility into session specifics, allowing users to easily track client authentication and version. - -A critical improvement in this release enhances the performance of processing received MQTT publish messages. Previously, two queues (one for messages, and another for acknowledgments) were used to handle this process, but with this update, we’ve streamlined it to a single, non-blocking queue. This optimization significantly boosts handling efficiency and reduces latency, making it ideal for high-throughput environments where fast message processing is crucial. - -This release brings a range of meaningful enhancements, each designed to improve the system’s transparency, security, and performance, paving the way for a more reliable and efficient MQTT experience. We invite you to try out these powerful new features by [installing the latest version of TBMQ](https://tbmq.io/docs/installation/). diff --git a/src/content/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations.mdx b/src/content/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations.mdx deleted file mode 100644 index ef833c1c05..0000000000 --- a/src/content/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: 'TBMQ 2.1: New chapter in MQTT messaging with embedded Integrations' -description: 'TBMQ 2.1 release: Integration Executor microservice with HTTP, Kafka, and MQTT outbound integrations, plus the official Helm Chart for K8s deployments.' -date: 2025-04-29 -updatedDate: 2025-04-29 -author: dlandiak -categories: ['updates'] -featuredImage: '/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/cover.webp' -featuredImageAlt: 'TBMQ 2.1 release' -draft: false ---- - -We’re excited to announce the release of TBMQ [2.1.0](https://tbmq.io/docs/releases/)! This version marks a major milestone by introducing the Integration Executor microservice, which is responsible for managing integrations. It powers scalable and multi-protocol message delivery to external systems, starting with support for HTTP, Kafka, and MQTT outbound integrations. We’ve also released the official [Helm Chart](https://tbmq.io/docs/installation/) for TBMQ, simplifying deployment and management of the infrastructure in K8s environments. - -## Integration executor - -![Integration executor architecture in TBMQ 2.1](/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/integration-executor-4.webp) - -At the heart of TBMQ 2.1 is the **Integration Executor** — a new dedicated microservice that launches and manages integrations in a scalable and resilient way, all built upon a **no data loss architecture** for maximum reliability. - -Rather than embedding integration logic inside the broker, TBMQ delegates this responsibility to the Integration Executor. This architecture ensures clean responsibility segregation, allowing the broker to focus on MQTT protocol handling while the executor takes care of message delivery to external systems. The result: better performance, isolation, and scalability. - -The Integration Executor communicates with TBMQ via Kafka, which acts as a buffer and transport layer. When an MQTT message matches an integration subscription, TBMQ transforms it into an integration event and routes it through Kafka to the appropriate executor instance. The executor then forwards it to the configured destination, such as an HTTP endpoint, a Kafka topic, or another MQTT broker. - -Highlights: - -- Clear separation between MQTT protocol logic and integration delivery. -- Built-in support for **HTTP**, **Kafka**, and **MQTT** outbound integrations. -- Horizontally scalable: run multiple executors in parallel. -- Each integration uses a **dedicated Kafka topic** for message processing isolation and high throughput. -- Advanced error handling with retry strategies and rich monitoring metrics. - -This architecture ensures fault-tolerant, no-loss message delivery, powered by Kafka-backed buffering and resilient processing. Learn more about how the Integration Executor works in our [official documentation](https://tbmq.io/docs/integrations/). - -## Integrations - -TBMQ 2.1 introduces a robust and extensible integration system, allowing you to forward MQTT messages to external systems for storage, processing, or real-time workflows. - -This release includes three outbound integration types: - -- **HTTP Integration** – Send MQTT messages to REST APIs or Webhooks over HTTP(S). -- **Kafka Integration** – Forward messages to Kafka topics using the native Kafka protocol over TCP(TLS). -- **MQTT Integration** – Bridge TBMQ to other MQTT brokers, enabling cross-broker communication over MQTT(S). - -Each integration is easy to configure through the TBMQ Web UI or REST API. You can define **topic filters**, connection parameters, and enable/disable integrations independently. When messages match the defined filters, they’re automatically routed to the correct external system, all handled asynchronously through the Integration Executor microservice. - -These integrations empower developers to: - -- Build **event-driven pipelines** across systems. -- Stream IoT data to **analytics platforms** or **data lakes**. -- Connect TBMQ with **legacy systems**, **cloud services**, or **third-party platforms**. - -With support for multiple integrations running in parallel, a scalable execution model, and guaranteed message delivery, TBMQ makes it easy to integrate MQTT data into your broader infrastructure. - -### HTTP integration - -![HTTP integration setup in TBMQ 2.1 embedded integrations](/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/http-1.webp) - -The **HTTP Integration** allows you to forward MQTT messages to REST APIs and Webhooks in real time. This is ideal for integrating TBMQ with cloud platforms, serverless functions, or any service that exposes an HTTP(S) endpoint. - -Key highlights: - -- Supports **HTTP and HTTPS** protocols. -- Customizable headers, payload format, and authentication options. -- Great for notifying external systems or activating business logic. - -Thanks to its simplicity and versatility, HTTP Integration is one of the most popular and widely applicable options for IoT and messaging pipelines. - -### MQTT integration - -![MQTT-to-MQTT integration setup in TBMQ 2.1](/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/mqtt-1.webp) - -The **MQTT Integration** lets you forward messages from TBMQ to external MQTT brokers, enabling **broker-to-broker communication**. This is useful in multi-tier or multi-region architectures. - -This integration makes it easy to connect TBMQ with other MQTT ecosystems, whether you’re relaying messages between cloud and edge, syncing environments, or bridging to legacy platforms. - -Key highlights: - -- Connects to other brokers using **MQTT or MQTTS**. -- Ideal for cross-broker communication, data replication, or interconnecting isolated clusters. -- Supports topic filters and customizable forwarding rules. -- Can act as a bridge between TBMQ and third-party brokers like Mosquitto, or ThingsBoard MQTT transport. - -Use this integration to extend TBMQ’s reach across environments — securely and efficiently. - -### Kafka integration - -![Kafka embedded integration in TBMQ 2.1](/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/kafka-1.webp) - -The **Kafka Integration** enables TBMQ to stream messages directly into Kafka topics using the **Kafka binary protocol** (TCP/TLS). It’s designed for high-throughput, event-driven data pipelines, and real-time processing. - -Key highlights: - -- Supports native Kafka connectivity. -- Automatically maps MQTT topics to Kafka topics. -- Ideal for big data, analytics, and stream processing use cases. -- Compatible with any Kafka deployment like Confluent, MSK, or self-managed clusters. - -This integration bridges the MQTT world with modern event streaming systems and allows for scalable downstream processing. - -## Helm chart - -![Helm chart deployment configuration for TBMQ 2.1](/images/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/helm-tbmq2.webp) - -Helm is the most widely adopted package manager for Kubernetes. It simplifies the deployment and management of complex applications by bundling all Kubernetes manifests and configuration options into reusable charts. With our [Helm chart](https://tbmq.io/docs/installation/?installationType=helm), TBMQ users can deploy the entire stack, including Broker nodes, Integration Executors, and dependencies, in a repeatable and standardized way using just a few commands. - -### Benefits of using Helm - -- **Faster deployments**: Helm enables quick, consistent setup of TBMQ in both development and production environments. -- **Configurability**: Users can easily override settings (e.g., database credentials, resource limits, and MQTT settings) via a `values.yaml` file without editing templates. -- **Environment-specific setups**: Maintain tailored configurations for development, staging, or production, reducing deployment errors. -- **Upgrades and rollbacks**: Helm tracks release history, making it easy to roll back to a stable version if something goes wrong. -- **CI/CD integration**: Helm naturally fits into GitOps workflows and automates cluster deployments in CI/CD pipelines. - -### What’s included in the TBMQ Helm chart? - -Our official chart provides everything you need to run TBMQ in a cloud-native way: - -- Core **TBMQ broker** deployment with support for MQTT and MQTT over TLS. -- **Integration Executor** microservice with configuration for supported integration types (HTTP, MQTT, Kafka). -- Built-in sub-charts deployment of **PostgreSQL**, **Redis**, and **Kafka**. -- Configurable Ingress with TLS, LoadBalancer services with TLS support, Kubernetes readiness/liveness probes, and persistent storage for stateful components. - -## Angular 19 - -We’ve upgraded the TBMQ UI from Angular 15 to Angular 19, bringing significant improvements in performance, user experience, and long-term maintainability. This upgrade also improves compatibility with modern libraries and tooling, ensuring that the platform remains future-ready. Alongside the version bump, we’ve replaced Angular Flex-Layout with Tailwind CSS for cleaner and faster styling and switched to Angular’s esbuild builder for improved build performance. These changes collectively result in a more responsive, polished, and maintainable interface. - -#### Final words - -We’re thrilled to bring you this powerful update, and we can’t wait to see what you build with it. -Check out the full documentation on [Integrations](https://tbmq.io/docs/integrations/) and deploy TBMQ 2.1 using our official [Helm Chart on ArtifactHub](https://artifacthub.io/packages/helm/tbmq-helm-chart/tbmq-cluster). -Support us by starring the [TBMQ GitHub repository](https://github.com/thingsboard/tbmq), sharing feedback, and opening issues or PRs. diff --git a/src/content/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking.mdx b/src/content/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking.mdx deleted file mode 100644 index 6b74ead990..0000000000 --- a/src/content/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: 'TBMQ 2.2: Strengthening MQTT security with JWT and Client Blocking' -description: 'TBMQ 2.2 release: pluggable JWT authentication, client blocking, and other security improvements for production MQTT deployments at scale.' -date: 2025-09-01 -updatedDate: 2025-09-01 -author: dlandiak -categories: ['updates'] -featuredImage: '/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/cover.webp' -featuredImageAlt: 'TBMQ 2.2 Release' -draft: false ---- - -We’re excited to announce the release of TBMQ [2.2.0](https://tbmq.io/docs/releases/)! This release brings powerful new features that make TBMQ more secure, resilient, and easier to operate in production at scale. - -With TBMQ 2.2, we focused on these key areas: - -- **Stronger security** — new pluggable authentication providers, including full support for **JWT authentication**, and the ability to block suspicious clients before they even reach the authentication stage. -- **Greater reliability under load** — advanced **backpressure handling** ensures subscribers that can’t keep up no longer put the broker at risk, protecting memory and maintaining stability. -- **Operational flexibility** — security and traffic control policies can now be adjusted **on the fly**, without restarts. - -Together, these improvements make TBMQ 2.2 the most secure and resilient release yet — ready to power demanding MQTT workloads across IoT, messaging, and event-driven systems. - -## MQTT authentication providers - -![MQTT authentication providers overview in TBMQ 2.2](/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/mqtt_authentication_providers.webp) - -Security has always been a cornerstone of TBMQ, and with this version, we’re taking a big step forward in how authentication is managed. Previously, TBMQ supported **Basic authentication (clientId/username/password)**, **X.509 certificate chain authentication**, and **SCRAM (MQTT 5.0)**. While these worked well, they were configured exclusively via YAML files or environment variables, meaning that every change required a broker restart. - -With TBMQ 2.2, authentication providers have been fully **moved into the database** and can now be configured on the fly — directly through the user interface or APIs — without downtime. This makes it significantly easier to adapt authentication policies in dynamic environments. - -### Pluggable authentication providers - -TBMQ now supports a flexible, pluggable model for authentication providers. The following methods are available and can be enabled, disabled, or tuned independently: - -- **Basic Authentication** — Authenticates clients using a clientId, username, and password sent in the CONNECT packet. -- **X.509 Certificate Chain** — Uses the client’s X.509 certificate chain during TLS handshake for authentication. -- **JWT Authentication (NEW)** — Authenticates clients using a signed JWT passed in the password field of the CONNECT packet. -- **SCRAM (MQTT 5.0 only)** — Performs a secure challenge-response using hashed credentials to authenticate without sending the actual password. - -Each provider can be controlled from the Authentication Providers page in the TBMQ UI. You can toggle providers, adjust their parameters, or dive deeper into provider details to fine-tune your security model. - -### Execution order - -Another improvement in TBMQ 2.2 is the **configurable execution order** of authentication providers. -From the **MQTT Authentication Settings** page, you can define the order in which TBMQ evaluates providers when handling client connections. This makes it possible to prioritize, for example, certificate-based authentication over username/password, or vice versa, depending on your deployment needs. - -### Why it matters - -This change turns authentication management from something static and operationally heavy into a dynamic, UI-driven process. Instead of restarts and manual environment variable changes, you now get: - -- Zero-downtime changes to authentication policies. -- Centralized management of all authentication methods. -- More flexibility for combining different auth strategies. - -This paves the way for the other security improvements in TBMQ 2.2, such as JWT-based authentication. - -## JWT authentication - -![JWT authentication configuration in TBMQ 2.2](/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/jwt_authentication_3x.webp) - -Starting with version 2.2, TBMQ introduces support for JWT (JSON Web Token) authentication for MQTT clients. This enables a secure, flexible, and scalable way to verify client identity using signed tokens, making it easier to integrate with centralized identity systems and enforce fine-grained access control. - -### How it works - -When an MQTT client connects, it places a **signed JWT token** into the `password` field of the `CONNECT` packet. TBMQ then: - -1. **Validates the token’s signature** using one of the supported verification methods: - -**HMAC secrets** (HS256/384/512) - -**Public keys in PEM format** (RSA, EC, Ed25519) - -**JWKS endpoints** (commonly used with providers like Keycloak, AWS Cognito, or Auth0) -2. **Checks standard claims** such as `exp` (expiration) and `nbf` (not before) to ensure the token is valid in time. -3. **Optionally validates custom claims** (e.g., ensuring the token `sub` matches the clientId or `mqtt_user` matches the username). -4. **Classifies the client type** (DEVICE or APPLICATION) based on token claims or defaults. -5. **Applies authorization rules** — either static, regex-based rules from the provider settings or **dynamic rules extracted directly from JWT claims** (for example, `pub_rules` and `sub_rules` claims defining which topics the client may publish or subscribe to). - -Only if all these steps succeed is the client allowed to connect and exchange data. - -### Why JWT matters for MQTT - -JWT brings a number of benefits to TBMQ users: - -- **Centralized identity integration** — Connect your broker to modern identity systems that issue JWTs. -- **No static credentials** — Eliminates the risks of managing passwords in configuration files or clients. -- **Dynamic authorization** — Authorization rules can be injected directly into tokens, making access control more flexible and adaptive. -- **Scalability & security** — Ideal for IoT deployments where thousands or millions of devices need secure, token-based authentication. - -## Blocked clients - -![Blocked clients management in TBMQ 2.2 security feature](/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/blocked_clients_3x.webp) - -Another major addition is the Blocked Clients feature — a proactive security tool that gives administrators more control over who can connect to the broker. - -With Blocked Clients, you can prevent unwanted or suspicious MQTT clients from establishing a connection, based on identifiers such as: - -- **Client ID** -- **Username** -- **IP address** -- **Regex-based rules** for more flexible pattern matching - -For example, if you detect a client like `attack-bot-23` attempting to flood the broker with repeated connection attempts, you can immediately block it by client ID — cutting off access before authentication even takes place. - -### How it works - -- **Early rejection:** Block checks happen **before authentication**, ensuring malicious traffic is stopped without consuming system resources. -- **Cluster-wide consistency:** Block rules are synchronized across all TBMQ nodes using Kafka, ensuring consistent enforcement in distributed deployments. -- **Temporary blocks:** Each entry can include an **expiration time**, after which it’s automatically cleaned up. This is useful for temporary quarantines or time-limited restrictions. - -### Why it matters - -The feature not only strengthens security but also helps **reduce load** on the broker by rejecting unwanted connections earlier in the pipeline. This improves both system stability and responsiveness under attack or heavy traffic. - -### Best practices - -- Use **exact matches** (Client ID, Username, IP) whenever possible — regex rules are powerful but more resource-intensive. -- Keep the blocked list lean for optimal performance. -- Combine blocking with standard authentication to create a **multi-layered defense strategy**. - -In short, Blocked Clients adds a new layer of protection, enabling administrators to quickly react to suspicious activity and maintain a secure, stable MQTT environment. - -## MQTT backpressure - -![MQTT backpressure handling diagram in TBMQ 2.2](/images/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/mqtt_backpressure.webp) - -High-throughput MQTT systems face a common challenge: what happens if subscribers cannot keep up with the flow of messages? Without safeguards, the broker’s buffers may grow uncontrollably, leading to excessive memory usage or even system crashes. - -With TBMQ 2.2, this problem is solved by introducing **backpressure-aware delivery**. Instead of overwhelming slow subscribers, TBMQ intelligently pauses and resumes message delivery based on the health of each client connection. - -### How it works - -TBMQ continuously monitors whether a client’s connection can accept new data. When a subscriber becomes overloaded: - -- **Message delivery is temporarily paused** once the connection buffer reaches a configured threshold. -- **Delivery resumes automatically** as soon as the connection is ready again. -- This ensures no single client can destabilize the broker or consume excessive resources. - -### Handling different client types - -TBMQ applies tailored strategies depending on the type of MQTT client: - -- **Non-persistent clients**: Messages are skipped if the client cannot keep up. This prevents memory buildup and aligns with MQTT expectations where message loss is acceptable for short-lived sessions. A counter tracks how many messages were dropped for visibility. -- **Persistent clients**: Messages are not lost. Instead, they are buffered until the connection recovers: - -**Devices** → messages are queued in Redis. - -**Applications** → messages are paused at the Kafka consumer level until the client is ready. - -This design guarantees durability for persistent sessions while protecting resources from runaway growth. - -### Shared Subscriptions - -Backpressure handling also extends to shared subscriptions. If one subscriber in a group slows down, TBMQ reroutes messages to other subscribers when possible. If all are overloaded, messages are safely buffered (for persistent groups) or dropped (for non-persistent groups). - -### Why it matters - -By making delivery backpressure-aware, TBMQ 2.2 ensures: - -- **Stable memory usage** even under heavy load. -- **Fair resource distribution** across fast and slow consumers. -- **No downtime or crashes** due to subscriber overload. - -In practice, this means your broker can handle **massive throughput** while staying resilient — delivering messages reliably to subscribers that can keep up, without being dragged down by those that can’t. - -## Final words - -TBMQ 2.2 delivers important advancements in security, reliability, and performance — but this post only scratches the surface. We encourage you to review the full [release notes](https://tbmq.io/docs/releases/) to explore all improvements and fixes included in this version. - -If you find TBMQ valuable, support us by **starring the [TBMQ GitHub repository](https://github.com/thingsboard/tbmq)**, sharing your feedback, and contributing through issues or pull requests. Your input helps us make TBMQ better with every release. diff --git a/src/content/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails.mdx b/src/content/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails.mdx deleted file mode 100644 index 87e9265c86..0000000000 --- a/src/content/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: 'TBMQ 2.3: External authentication, bulk provisioning, and enterprise audit trails' -description: 'TBMQ 2.3 release: HTTP external authentication, bulk MQTT client provisioning, and Professional Edition audit logs, SSO role mapping, and Redis ACL support.' -date: 2026-05-12 -updatedDate: 2026-05-12 -author: dlandiak -categories: ['updates'] -featuredImage: '/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/cover.webp' -featuredImageAlt: 'TBMQ 2.3 release' -draft: false ---- -import BlogCTA from '~/components/Blog/BlogCTA.astro'; - -We're excited to announce the release of TBMQ 2.3.0 ([Community Edition](https://tbmq.io/docs/releases/) / [Professional Edition](https://tbmq.io/docs/pe/releases/#v230PE)). This version extends how TBMQ handles authentication, scales operator workflows for large client fleets, and strengthens the enterprise controls in the Professional Edition. - -Here's what's new in 2.3 across both editions: - -| New in TBMQ 2.3 | Community | Professional | -| --------------------------------------- | :-------: | :----------: | -| HTTP authentication provider | ✓ | ✓ | -| Bulk import of MQTT client credentials | ✓ | ✓ | -| TLS + ACL for Redis/Valkey | ✓ | ✓ | -| Audit logs | — | ✓ | -| SSO role mapping | — | ✓ | - -Let's take a closer look at each change, starting with Community Edition. - -## Community Edition - -### HTTP authentication provider - -![TBMQ HTTP authentication provider settings with sample request and response JSON](/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-http-auth.webp) - -[TBMQ 2.2](https://tbmq.io/docs/releases/#v220-september-1-2025) moved the broker's authentication providers into the database and made them pluggable. With 2.3, we've extended that framework with a new provider that delegates client authentication to an external HTTP service. - -With the HTTP authentication provider enabled, every MQTT `CONNECT` attempt is forwarded as a signed HTTP request to an endpoint you configure. The response drives the authentication decision — accept or reject, together with the client type (`DEVICE` or `APPLICATION`) and the authorization rules TBMQ should enforce for the session. - -**How it works** - -1. On `CONNECT`, TBMQ serializes the client credentials (client ID, username, password, and — for mTLS connections — the client certificate's Common Name) into a JSON request. -2. TBMQ sends that request to your configured endpoint, applying the headers and timeout you've set. -3. Your service evaluates the credentials against whatever identity store or policy engine you already run, and returns a response body with the authentication verdict and optional authorization rules. -4. TBMQ uses the response to allow or deny the connection, and to apply per-topic pub/sub rules for the session. - -**Why it matters** - -Teams with bespoke identity systems — internal IAM, policy engines, HR directories, multi-tenant authorization services — often can't express their auth logic as credentials stored in TBMQ (Basic, X.509, SCRAM) or as claims encoded in a JWT. The decision itself lives in their own service, and the broker simply needs to ask. The HTTP provider lets that logic stay where it already lives, and still gives you broker-side enforcement at connect time. It also composes with the existing providers: you can order HTTP behind JWT, or in front of Basic, depending on how you want credentials evaluated. - -For full configuration details, request/response schemas, and end-to-end setup examples, see the [HTTP authentication provider](https://tbmq.io/docs/security/authentication/http/) guide. - -### Bulk import of MQTT client credentials - -![TBMQ MQTT client credentials bulk import: CSV upload, column mapping, and results summary](/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-bulk-import.webp) - -Provisioning a handful of clients through the UI is fine. Provisioning tens of thousands — typical for an IoT rollout, a migration from another broker, or an environment with per-device certificates — is not. - -TBMQ 2.3 adds bulk import of MQTT client credentials through a CSV upload. You supply a CSV describing the Basic credentials to provision — with columns for name, client type, client ID, username, password, subscribe and publish topic patterns, and description — and TBMQ processes it as an **upsert**: entries are matched by their **Name**, with new rows created and matching rows updated in place. - -Column mapping is interactive, so your CSV doesn't have to match a fixed layout. After processing, the importer reports how many credentials were created, updated, or rejected, so partial batches surface actionable errors instead of silently skipping rows. - -This closes the main onboarding gap that teams hit when moving production fleets onto TBMQ, and removes the need to script provisioning against the per-credential API for bulk operations. - -The [bulk provisioning guide](https://tbmq.io/docs/other/bulk-provisioning/) walks through the CSV format, the interactive column mapping, and how passwords and authorization rules are handled on create and update. - -### Secure Redis/Valkey connections - -TBMQ stores persistent device messages and other hot-path state in Redis (or Valkey). Until 2.3, the broker connected to that store over plaintext and without user-scoped ACLs — acceptable inside a private network, but limiting as soon as the data store lives behind a managed endpoint or crosses a trust boundary. - -TBMQ 2.3 adds SSL/TLS support and ACL username authentication for the broker's Redis/Valkey connection. You can now: - -- Terminate the broker → Redis connection over TLS with standard certificate validation. -- Authenticate using an ACL username alongside the password, matching the Redis 6+ / Valkey ACL model. -- Run TBMQ against managed services that mandate encrypted connections and per-user credentials — AWS ElastiCache, GCP Memorystore, managed Valkey offerings — without proxies or sidecars. - -Configuration parameters are described in the [TBMQ configuration reference](https://tbmq.io/docs/installation/config/#redis-configuration-parameters). - -### Other improvements - -The release also includes a number of narrower updates: - -- **Modernized infrastructure.** The reference stack has moved to Apache Kafka 4.0, Valkey 8.0 (as a drop-in alternative to Redis > 7.2), and PostgreSQL 17. Operators should review the new infrastructure versions in the full release notes before upgrading. -- **Session management refactor.** Session-management internals have been refactored for performance and race-condition fixes. -- **UI.** Home, login, and getting-started pages were refreshed; monitoring charts were updated; and the UI now ships Spanish, Hindi, and Simplified Chinese translations. -- **Per-listener proxy protocol.** Proxy protocol can now be enabled or disabled independently for each MQTT listener (TCP, TLS, WS, WSS). -- **CN placeholder in X.509 rules.** Certificate Common Name can be used as a placeholder inside authorization rules, simplifying dynamic, certificate-driven policies. -- **Dependency security.** HIGH and MEDIUM CVEs in Spring Boot, Netty, Tomcat, Jackson, Logback, and BouncyCastle have been addressed. - -## Professional Edition - -TBMQ PE 2.3 inherits every change above and adds the following PE-exclusive capabilities. - -### Audit logs - -![TBMQ PE audit logs page with an entry details panel showing the JSON action_data payload](/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-audit-logs.webp) - -Until now, tracing administrative activity inside TBMQ — who changed what, and when — meant piecing the trail together from application logs and container output. TBMQ PE 2.3 replaces that exercise with a built-in audit log. - -Every administrative action and significant system event is now recorded as an audit entry: user logins, credential changes, integration configuration updates, and role assignments. Entries capture the actor, the target entity, the action type, a timestamp, and an action data payload with the full context of what was applied — for a login, the client address, browser, OS, and device; for a configuration change, the resulting entity state. - -The audit log is queryable from the PE UI and via the REST API, with filtering by actor, action type, and time window. Retention is configurable so that operators can match their compliance posture without carrying unbounded history. - -Typical uses: compliance reporting (SOC 2, ISO 27001, HIPAA), post-incident forensics, and day-to-day security monitoring. - -For the full list of audited events, retention settings, and the query API, see the [audit log](https://tbmq.io/docs/pe/security/audit-log/) documentation. - -### SSO role management - -![TBMQ PE OAuth 2.0 Basic mapper mapping IdP attribute values to Administrator and Viewer roles](/images/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/feature-sso-roles.webp) - -[TBMQ PE 2.2](https://tbmq.io/docs/pe/releases/#v220PE) introduced Single Sign-On alongside RBAC. At the time, the Basic mapper could only stamp a **single fixed role** on every user coming from a given OAuth 2.0 client, so administrators had to reassign roles by hand as users arrived — painful at enterprise scale and a frequent source of drift. - -TBMQ PE 2.3 adds **dynamic role assignment** to the Basic mapper. Each OAuth 2.0 client can now derive a user's TBMQ role from an attribute in the identity provider's user info response — typically `roles` or `groups` — instead of assigning the same role to every incoming user. - -- **Static or dynamic, per client.** Keep the 2.2 behavior (one fixed role) or switch a specific client to dynamic mode. -- **Attribute-driven mapping.** Pick the user info attribute to read, then list the values that should grant **Administrator** and the values that should grant **Viewer**. -- **Deterministic precedence.** If a user's attribute values match both lists, Administrator wins. -- **No IdP changes.** The mapping lives inside the TBMQ OAuth 2.0 client configuration — no change to the identity provider or to the OAuth 2.0 flow itself. - -The practical outcome: users provisioned via SSO arrive in TBMQ with the right role already set, based on their IdP attributes — no manual role-assignment step for each new user. The mapping is evaluated when the account is created, so subsequent attribute changes in the IdP don't automatically update an existing user's role; role changes for existing users stay under TBMQ administrator control. - -For full configuration details and walkthroughs for Google, Auth0, and Keycloak, see the [OAuth 2.0 and SSO — Basic mapper](https://tbmq.io/docs/pe/security/oauth-2-support/#basic-mapper) documentation. - -## Final words - -TBMQ 2.3 tightens the broker's fit for demanding deployments at both ends of the spectrum: flexible external authentication and smoother large-fleet operations for Community Edition users, and first-class audit trails plus automated SSO role mapping for Professional Edition users running in regulated environments. - -For the complete list of changes, see the [Community Edition release notes](https://tbmq.io/docs/releases/) and the [Professional Edition release notes](https://tbmq.io/docs/pe/releases/). - -If you find TBMQ useful, support the project by starring the [TBMQ GitHub repository](https://github.com/thingsboard/tbmq) and by opening issues or pull requests. - - diff --git a/src/data/blog/posts.ts b/src/data/blog/posts.ts index 99a999a6c3..22c5afdb6b 100644 --- a/src/data/blog/posts.ts +++ b/src/data/blog/posts.ts @@ -1,4 +1,5 @@ import { getCollection, type CollectionEntry } from 'astro:content'; +import { BLOG_AUTHORS, type BlogAuthor } from '@data/blog/authors'; export type BlogPost = CollectionEntry<'blog'>; @@ -14,3 +15,17 @@ export async function getSortedBlogPosts( const posts = await getCollection('blog', filter); return posts.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); } + +/** + * Authors from `BLOG_AUTHORS` that are the byline of at least one post. + * + * `BLOG_AUTHORS` is the full byline roster and can outlive the posts it was + * written for — entries whose posts were removed or moved to another site stay + * behind, so mapping it directly would build author landing pages with nothing + * to list. Route enumerators filter through here instead. + */ +export async function getAuthorsWithPosts(): Promise { + const posts = await getCollection('blog'); + const authorSlugs = new Set(posts.map((post) => post.data.author)); + return BLOG_AUTHORS.filter((author) => authorSlugs.has(author.slug)); +} diff --git a/src/data/redirects.ts b/src/data/redirects.ts index 564727940e..1f5806a61f 100644 --- a/src/data/redirects.ts +++ b/src/data/redirects.ts @@ -1353,6 +1353,16 @@ export const NON_DOCS_REDIRECTS: Record = { '/products/mqtt-broker/terms-of-use/': `${TBMQ_ORIGIN}/product/terms-of-use/`, // Demo CA cert removed with the TBMQ docs; the TBMQ site serves its own copy '/resources/tbmq-demo-root-ca.pem': `${TBMQ_ORIGIN}/resources/tbmq-demo-root-ca.pem`, + // TBMQ blog posts moved to tbmq.io with the same slugs; the local .mdx files + // (and their public/images/blog/ dirs) are deleted. Author pages are built only + // for authors with remaining posts, so the now-postless ones drop out unredirected. + '/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/': `${TBMQ_ORIGIN}/blog/1-million-reasons-to-choose-tbmq-as-high-performance-mqtt-broker/`, + '/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/': `${TBMQ_ORIGIN}/blog/introducing-tbmq-professional-edition-the-mqtt-broker-for-enterprise-needs/`, + '/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more/': `${TBMQ_ORIGIN}/blog/tbmq-1-3-0-release-websocket-client-advanced-mqtt-5-features-and-more/`, + '/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/': `${TBMQ_ORIGIN}/blog/tbmq-2-0-migration-to-redis-mqtt-5-0-support-and-more/`, + '/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/': `${TBMQ_ORIGIN}/blog/tbmq-2-1-new-chapter-in-mqtt-messaging-with-embedded-integrations/`, + '/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/': `${TBMQ_ORIGIN}/blog/tbmq-2-2-strengthening-mqtt-security-with-jwt-and-client-blocking/`, + '/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/': `${TBMQ_ORIGIN}/blog/tbmq-2-3-external-authentication-bulk-provisioning-and-enterprise-audit-trails/`, // Trendz '/products/trendz/trndz-request-demo/': '/products/trendz/request-demo/', diff --git a/src/pages/blog/author/[author].astro b/src/pages/blog/author/[author].astro index d46161d2c1..bc10d8f932 100644 --- a/src/pages/blog/author/[author].astro +++ b/src/pages/blog/author/[author].astro @@ -2,10 +2,11 @@ import BlogLayout from '../../../layouts/BlogLayout.astro'; import Breadcrumbs from '@components/Breadcrumbs.astro'; import BlogCard from '~/components/Blog/BlogCard.astro'; -import { getSortedBlogPosts } from '@data/blog/posts'; -import { BLOG_AUTHORS, type BlogAuthor } from '~/data/blog/authors'; -export function getStaticPaths() { - return BLOG_AUTHORS.map((author) => ({ +import { getAuthorsWithPosts, getSortedBlogPosts } from '@data/blog/posts'; +import type { BlogAuthor } from '@data/blog/authors'; +export async function getStaticPaths() { + const authors = await getAuthorsWithPosts(); + return authors.map((author) => ({ params: { author: author.slug }, props: { author }, })); @@ -30,13 +31,7 @@ const posts = await getSortedBlogPosts((p) => p.data.author === author.slug);
- {posts.length === 0 ? ( -

No posts by this author yet.

- ) : ( - posts.map((post) => ( - - )) - )} + {posts.map((post) => )}
@@ -65,6 +60,4 @@ const posts = await getSortedBlogPosts((p) => p.data.author === author.slug); @include media-down(lg) { grid-template-columns: repeat(2, 1fr); } @include media-down(sm) { grid-template-columns: 1fr; } } - - .no-posts { @include text-m; color: var(--color-text-secondary); text-align: center; grid-column: 1 / -1; padding: var(--spacing-10); } diff --git a/src/pages/open-graph/_shared/page-data.ts b/src/pages/open-graph/_shared/page-data.ts index fbc5a7719c..fe341879bb 100644 --- a/src/pages/open-graph/_shared/page-data.ts +++ b/src/pages/open-graph/_shared/page-data.ts @@ -14,6 +14,7 @@ import type { CardProps } from '@root/pages/open-graph/_shared/Card'; import { getDocsProductMeta } from '@root/pages/open-graph/_shared/product-meta'; import { getMarketingOverride, getMarketingSection } from '@root/pages/open-graph/_shared/marketing-meta'; import { BLOG_AUTHORS } from '@data/blog/authors'; +import { getAuthorsWithPosts } from '@data/blog/posts'; import { CATEGORY_LABELS } from '@data/blog/categories'; import { HARDWARE_PARTNERS } from '@data/partners/hardware-partners'; import { IOT_HUB_CATEGORIES } from '@models/iot-hub'; @@ -91,8 +92,8 @@ export async function getBlogCardInputs(): Promise { }, }); - // /blog/author/{author-slug}/ - for (const author of BLOG_AUTHORS) { + // /blog/author/{author-slug}/ — only authors that still have posts get a route + for (const author of await getAuthorsWithPosts()) { inputs.push({ slug: `author/${author.slug}`, props: {