Enhancements
Message Queue
-
#16080 Added a configuration option to disable the Message Queues feature. Disabling Message Queues can slightly reduce the resource usage in the cluster. When Durable Sessions are also disabled, EMQX avoids maintaining Durable Storage, further reducing administrative overhead and improving performance.
-
#16096 Added support for automatic creation of message queues when clients subscribe to non-existent
$q/topics. Now configuration options are available to enable auto-creation for both regular and last-value semantics queues. -
#16097 Optimized message writing to regular message queues by replacing transactional appends with dirty append functions. For QoS 0 messages, asynchronous append operations are now used. These changes significantly improve the performance of message insertion into regular queues.
-
#16098 Added a maximum queue count configuration option to limit the total number of message queues in the system.
-
#16152 Introduced per-queue limits for maximum message count and total message size. Also added new metrics to monitor message append latency and help diagnose performance or queue-limiting issues.
Data Integration
- #16121 Upgraded the GreptimeDB ingester client to v0.2.3, which fixes several bugs and introduces support for row-based gRPC protocol (the column-based protocol is now deprecated).
Additionally, updated the CI image to the latest stable version of GreptimeDB.
- #16127 Fixed an invalid string value issue in the GreptimeDB connector, following the changes introduced in #16121.
Performance
- #15949 Changed the default value of the
parse_unitoption in listener configuration fromchunktoframe. This change can significantly reduce CPU usage when the payload size exceeds the socket buffer (default is 4 KB).
Note: With parse_unit = frame, if a PUBLISH packet exceeds the maximum allowed size, EMQX will close the connection instead of sending a DISCONNECT packet.
- #16165 Optimized the performance of the
GET /clients_v2API. Previously, when the cluster had around 50,000 clients or more, API calls to retrieve the client list could be extremely slow or even time out.
Bug Fixes
Core MQTT Functionalities
-
#15884 Resolve an issue where, in rare cases, the global routing table could indefinitely retain routing information for nodes that had long left the cluster.
-
#15518 Resolved a race condition that may lead to accumulating inconsistencies in the routing table and shared subscriptions state in the cluster when a large number of shared subscribers disconnect simultaneously.
Upgrade
- #16047 Added support to perform rolling upgrade from EMQX Enterprise base version 5.8.0 and newer to 6.0. During the upgrade, legacy configurations are automatically migrated to the new format supported in 6.0. Specifically, the deprecated
bridgesconfiguration root is converted into the newconnectors,sources, andactionsroots.
However, the GCP PubSub Consumer and Kafka Consumer sources will still require manual changes. If any source configuration still includes the deprecated topic_mapping field, it must be removed. Then, for each entry previously defined in topic_mapping, a separate "Source + Rule" pair must be created manually.
Security
- #16156 Fixed an issue where some dependencies were missing default configurations compared to EMQX 5.10, potentially causing RSA signature verification failures. The missing defaults could lead to errors, such as the following log message:
{sign_unsupported,[[{rsa_padding,rsa_pkcs1_padding}]]}, [{jose_jwa_unsupported,verify,5,[{file,"src/jwa/jose_jwa_unsupported.erl"},{line,55}]}
- #16175 Fixed an issue with periodic TLS certificate garbage collection. Previously, the garbage collection process incorrectly deleted certificate files that were actively used by configurations in managed namespaces.
Access Control
- #16081 Fixed an issue where clients using extended authentication and memory-based sessions could crash with a
session_stepdown_request_exceptioncaused by acalling_selferror.
Example error log
``` 2025-09-24T07:13:08.973954+08:00 [error] clientid: someclientid, msg: session_stepdown_request_exception, peername: 127.0.0.1:41782, username: admin, error: exit, reason: calling_self, stacktrace: [{gen_server,call,3,[{file,"gen_server.erl"},{line,1222}]},{emqx_cm,request_stepdown,4,[{file,"emqx_cm.erl"},{line,427}]},{emqx_cm,do_takeover_begin,2,[{file,"emqx_cm.erl"},{line,398}]},{emqx_cm,takeover_session,2,[{file,"emqx_cm.erl"},{line,384}]},{emqx_cm,takeover_session_begin,2,[{file,"emqx_cm.erl"},{line,305}]},{emqx_session_mem,open,4,[{file,"emqx_session_mem.erl"},{line,210}]},{emqx_session,open,3,[{file,"emqx_session.erl"},{line,263}]},{emqx_cm,'-open_session/4-fun-1-',4,[{file,"emqx_cm.erl"},{line,290}]},{emqx_cm_locker,trans,2,[{file,"emqx_cm_locker.erl"},{line,32}]},{emqx_channel,post_process_connect,2,[{file,"emqx_channel.erl"},{line,575}]},{emqx_connection,with_channel,3,[{file,"emqx_connection.erl"},{line,852}]},{emqx_connection,process_msg,2,[{file,"emqx_connection.erl"},{line,470}]},{emqx_connection,process_msgs,2,[{file,"emqx_connection.erl"},{line,462}]},{emqx_connection,handle_recv,3,[{file,"emqx_connection.erl"},{line,406}]},{proc_lib,wake_up,3,[{file,"proc_lib.erl"},{line,340}]}], action: {takeover,'begin'}, ... ```Clustering
- #16123 Fix a bug in the component managing Mria replication that could cause cluster joins to hang or remain incomplete in core-replicant clusters.
During cluster changes involving adding new core nodes, those new core nodes could sometimes fail to start replication-related processes required by replicants. As a result, upgraded or newly added replicants could hang during startup.
In Kubernetes deployments, this often caused readiness probes to fail, leading the controller to repeatedly restart the affected replicant pods.
This issue typically affected upgrade rollouts involving the addition of new core and replicant nodes. For example, adding two cores and two replicants (running a newer EMQX version) to an existing cluster with 2 cores and 2 replicants.
Rule Engine
- #16028 Fixed rule engine
jqfunction memory leak.
Previously if jq built-in function index is used (e.g. .key | index("name")), it would result in memory leak.
Data Integration
- #16010 Fixed an issue where a Republish Fallback Action could fail with a
function_clauseerror if the originating rule's SQL did not include themetadatafield from the rule environment.
Example error log:
[error] tag: RESOURCE, msg: failed_to_trigger_fallback_action, reason: {error,function_clause}, fallback_kind: republish, primary_action_resource_id: <<"action:type:name:connector:type:name">>, republish_topic: <<"republish/topic">>
-
#16046 Fixed a potential out-of-memory (OOM) crash when loading or restarting a configuration containing a Connector with several hundred Actions.
-
#16140 Fix a Redis cluster failover issue that could cause the Connector to remain stuck in a "connecting" state.
Previously, EMQX’s Redis cluster client only refreshed the cluster topology when regular queries (such as GET) failed. However, failures in periodic PING commands did not trigger a refresh. As a result, after a failover, the connector could continue using the outdated cluster topology if no other commands were issued, preventing recovery.
With this fix, failed PING responses now trigger a cluster topology refresh, ensuring that the connector can detect failovers and recover promptly.
MQTT Durable Sessions
-
#16105 Durable storage performance optimization. In particular, this fix reduces the latency of
CONNACKfor clients using a durable session. -
#16129 Durable storage transaction configuration can be changed in the runtime. Previously changing this configuration required a node restart.
Observability
-
#15963 Reduced excessive audit log entries generated during looped evaluations in the remote shell (
remsh). -
#15967 Fixed an issue where Mnesia transaction blocking during the cleanup of large volumes of audit logs could lead to rapid memory growth.
-
#16060 Fixed a logger formatter crash that could occur for some debug-level log messages containing deeply nested terms with non-ASCII characters.
Example error log
``` 2025-09-29T06:55:34.120640+00:00 debug: FORMATTER CRASH: {report,#{request => #{messages => [#{role => <<"user">>,content => <<"{\"msg\": \"hello\"}">>}],system => <<"将输入的 JSON 数据中,值为数字的 value 相加起来,并输出,只需返回输出结果。"/utf8>>,model => <<"claude-3-haiku-20240307">>,max_tokens => 100},msg => emqx_ai_completion_request}} 2025-09-29T06:55:34.120780+00:00 [debug] formatter_crashed: emqx_logger_textfmt, config: #{time_offset => [],chars_limit => unlimited,depth => 100,single_line => true,template => ["[",level,"] ",msg,"\n"],with_mfa => false,timestamp_format => auto,payload_encode => text}, log_event: #{meta => #{line => 44,pid => <0.281254.0>,time => 1759128934120640,file => "emqx_ai_completion_anthropic.erl",gl => <0.4317.0>,mfa => {emqx_ai_completion_anthropic,call_completion,3},report_cb => fun logger:format_otp_report/1,matched => <<"t/1">>,namespace => global,clientid => <<"c_emqx">>,trigger => <<"t/1">>,rule_id => <<"r1sczoo0">>,rule_trigger_ts => [1759128934120]},msg => {report,#{request => #{messages => [#{role => <<"user">>,content => <<"{\"msg\": \"hello\"}">>}],system => <<"将输入的 JSON 数据中,值为数字的 value 相加起来,并输出,只需返回输出结果。"/utf8>>,model => <<"claude-3-haiku-20240307">>,max_tokens => 100},msg => emqx_ai_completion_request}},level => debug}, reason: {error,badarg,[{erlang,iolist_to_binary,[["[",[["messages",": ",[[91,[[35,123,[["role"," => ",[60,60,"\"user\"",62,62]],44,["content"," => ",[60,60,"\"{\\\"msg\\\": \\\"hello\\\"}\"",62,62]]],125]],93]]],", ",["system",": ","将输入的 JSON 数据中,值为数字的 value 相加起来,并输出,只需返回输出结果。"],", ",["model",": ","claude-3-haiku-20240307"],", ",["max_tokens",": ","100"]],"]"]],[{error_info,#{module => erl_erts_errors}}]},{emqx_trace_formatter,format_term,2,[{file,"emqx_trace_formatter.erl"},{line,126}]},{emqx_logger_textfmt,format_term,2,[{file,"emqx_logger_textfmt.erl"},{line,230}]},{emqx_logger_textfmt,try_encode_meta,4,[{file,"emqx_logger_textfmt.erl"},{line,206}]},{lists,foldl_1,3,[{file,"lists.erl"},{line,2151}]},{emqx_logger_textfmt,enrich_report,3,[{file,"emqx_logger_textfmt.erl"},{line,102}]},{emqx_logger_textfmt,format,2,[{file,"emqx_logger_textfmt.erl"},{line,24}]}]} ```- #16134 Fixed a backward compatibility issue that could prevent new Log Traces from being created in some cases.
Rate Limit
- #16160 Improved the rate limiting algorithm for individual client connections. Previously, clients could temporarily exceed their publish rate limits, particularly just after connecting or after periods of inactivity.
This update makes the limiter behavior more predictable and consistent, ensuring rate limits are correctly enforced from the start of a connection.
Breaking Changes
- #16061 Fixed an issue where RocketMQ actions ignored the configured payload template and sent the entire rule output instead.
If you relied on the previous (incorrect) behavior, you may need to update your payload templates to ensure messages are formatted as expected.