Download Latest Version emqx-enterprise-5.10.0-amzn2023-amd64.tar.gz (91.6 MB)
Email in envelope

Get an email when there's a new version of emqx

Home / e5.9.0
Name Modified Size InfoDownloads / Week
Parent folder
EMQX Enterprise 5.9.0 source code.tar.gz 2025-05-02 5.5 MB
EMQX Enterprise 5.9.0 source code.zip 2025-05-02 7.1 MB
README.md 2025-05-02 32.1 kB
Totals: 3 Items   12.7 MB 0

Release Date: 2025-05-02

Enhancements

Core MQTT Functionalities

  • #14721 Delayed publish interval limit changed from 4294967 seconds (49.7 days) to 42949670 seconds (497 days).

  • #14595 Deprecate retainer.enable flag. Retainer starts and stops automatically based on the mqtt.retain_available flag in zone configurations.

Installation and Deployment

  • #14930 Start releasing macOS 15 (Sequoia) packages.
  • #14590 Limit the maximum uptime for a node running under evaluation license to one month. After reaching the uptime limit, the node will reject new connections.

Namespace

  • #14261 Introduced enhancements to facilitate namespace in MQTT client management.

New features:

  • Namespace Client Recognition: MQTT clients with a tns attribute are now treated as namespace clients.
  • Namespace Indexing: Added the MQTT client namespace (tns) to the client ID index to support multi-tenancy scenarios.

APIs:

  • List Namespaces: Introduced a paginated API to retrieve namespaces: Endpoint: /api/v5/mt/ns_list
  • List Client Sessions in a Namespace: Added a paginated API to fetch client sessions within a specific namespace: Endpoint: /api/v5/mt/:ns/client_list
  • Count Live Client Sessions in a Namespace: New API to retrieve the number of active client sessions in a namespace: Endpoint: /api/v5/mt/:ns/client_count

Configuration:

  • Session Limit Per Namespace: Added the multi_tenancy.default_max_sessions configuration to enforce limits on the number of client sessions allowed per namespace.

Notes:

  • Admin namespace (admin user groups) is not included in this pull request and remains under development.

  • #14884 Added HTTP API to manage Namespace configurations.

  • #14840 Added HTTP API endpoints to configure client and tenant rate limiters for Namespace feature.

Authentication and Authorization

  • #14584 Added support authenticator app for Dashboard 2FA (2-factor authentication) login.

  • #14979 Added support for zone and listener in authentication and authorization templates. Also added zone and listener to the who match conditions in ACL rules.

This enables per-listener or per-zone access control. Examples:

  • Send the zone name in requests to the HTTP authenticator using a body template like: {"username": "${username}", "zone": "${zone}"}

  • In acl.conf, allow clients to subscribe to ${username}/# only if connected via the SSL listener: {allow, {listener, "ssl:default"}, subscribe, ["${username}/#"]}.

  • #14976 Added support for the precondition configuration for authenticators.

This allows selective invocation of authenticators based on client information, helping avoid unnecessary authentication requests. For example, to trigger the HTTP authenticator only for clients connected via tcp:default, and Postgre authenticators for those on ssl:default, you can use preconditions like str_eq(listener, 'tcp:default') or str_eq(listener, 'ssl:default').

  • #14966 Added the possibility of deleting the default Dashboard admin user. For that, at least one other admin user must exist.

  • #14358 Limit variables used in LDAP authentication/authorization templates to the ones that are allowed in the other authentication/authorization sources. The unsupported variables are kept unrendered.

  • #14610 Handle additional fields in authorization rules fetched from the external sources or stored in the built-in database.

The new supported fields are:

username_re: A regex for filtering rules by username.

clientid_re: A regex for filtering rules by clientid.

ipaddr: An IP address/mask for filtering rules by IP address.

A rule is applied only if all the present filters match.

  • #14329 Made ${peerport} variable available for use in templates of external requests made by authentication and authorization.

  • #14286 Implemented node-level cache for authorization and authentication.

Some authentication and authorization methods require an external service to be called. This may result in excessive load on EMQX and the external service, especially when clients reconnect frequently.

This feature provides a way to enable node-level caching for such authentication and authorization methods. Caching is available for the authnetication and authorization backends with the following mechanisms:

  • HTTP
  • LDAP
  • MongoDB
  • MySQL
  • PostgreSQL
  • Redis

REST API

  • #14254 Return cluster name in /status HTTP endpoint.
  • #14972 Implemented API methods for downloading/uploading individual plugin configs.
  • #15013 Added a new action_details field to the rule information returned by Rule Engine HTTP APIs. This new fields contains the type, name and status of actions referenced by each rule.
  • #14735 Added a last_modified_at field to rule information in Rule Engine HTTP APIs.

Clustering

  • #14766 Added safeguards to emqx ctl cluster leave command to prevent nodes responsible for Durable Storage data replication from leaving the cluster.

  • #14040 Added timeouts to the internal RPC calls during node rebalance. Previously, the rebalance process could hang if a node was unresponsive.

  • #14892 Enhanced cluster load rebalancing:

    • Fixed load imbalance in core/replicant cluster. Previously, under certain conditions, all transactions from the replicants could be sent to a single core node.
  • Add CLI commands for rebalancing replicant nodes in relation to core nodes:

    • emqx_ctl cluster core rebalance plan

    • emqx_ctl cluster core rebalance status

    • emqx_ctl cluster core rebalance confirm

    • emqx_ctl cluster core rebalance abort

  • #14907 Improved stability of node evacuation. Previously, the evacuation could enter a dead loop and require manual intervention to recover.

Data Integration

  • #14118 Support ON DUPLICATE KEY UPDATE in Mysql actions.

Now the user can specify ON DUPLICATE KEY UPDATE in the mysql action, e.g.:

INSERT INTO t1 (a,b,c) VALUES (${id},${clientid},${qos}) ON DUPLICATE KEY UPDATE a=a;

Note that the ON DUPLICATE KEY UPDATE clause doesn't support placeholders (${var}).

  • #14629 Added support for JSON Lines container types for S3 and Azure Blob Storage Actions.

  • #14642 Added new Connector and Action types that allow logging events to local disk in JSON lines format.

  • #14996 RabbitMQ action supports using the default exchange.

  • #14901 Added a new type of schema to Schema Registry: external_http. With this new schema type, it's possible to setup an external HTTP server that performs arbitrary operations to the payload and return the result to be used in Rules.

  • #14722 Added a new connect_timeout option to MQTT Connector. This controls how long in seconds the connection process is allowed to be stuck waiting to establish connection. Lower values may improve connection problem feedback times.

  • #14615 Added support for configuring the max_inactive parameter for several integrations that utilize the ehttpc HTTP driver.

  • #14459 Added support for Fallback Actions.

These are triggered when a message fails to be successfully processed by a Data Integration Action, including when it's dropped due to buffer overflow or to its time to live being reached. They can be configured for all Data Integration Actions.

Sample configuration snippet for a Kafka Action:

actions.kafka_producer.my_action { fallback_actions = [ {kind = reference, type = mqtt, name = mqtt_fallback_publisher}, {kind = republish, args = {topic = "fallback/action/republish"}} ] # ... }

  • #14582 Avoid pre- and post-processing of internal JSON representation before serialization and after deserialization respectively, in cases where it is completely unnecessary.

Administration

  • #14845 Avoid unnecessary restarts of existing listeners when changing gateway configurations and listeners.

  • #14773 Improved rate-limiting functionality (bytes_rate, messages_rate, max_conn_rate configured for zones or listeners).

  • The rate-limiting algorithm is simplified to work more predictably. It does not try to impose backpressure on the client(s). Instead, it drops the messages. For QoS1/QoS2 messages the appropriate reason code is also returned.

  • Rate limiting now allows reconfiguration at runtime.
  • Rate limiting configuration now allows to specify window size and limit per each window explicitly: messages_rate = "300/5m" means 300 messages per 5 minutes (with any possible fluctuation within this period), while messages_rate = "10/10s" means 10 messages per 10 seconds. Although the configured RPS is the same, the latter variant is much more strict about fluctuations in the actual rate.
  • Burst rate is provided via the messages_burst, bytes_burst, max_conn_burst zone and listener options. The burst value messages_burst = 1000/h means a client can send 1000 additional messages each hour without applying rate limiting.
  • #14341 This enhancement allow the namespace feature to support per-namespace session count limit. It support quota_exceeded error reason from client.authenticate hook point callback.
  • #14679 Updated the exhook.proto to v3 for passing User-Property parameters in the OnMessagePublish callback.
  • #14963 Provide plugins with the ability health status with the new on_health_check/1 callback. Export health status via HTTP API and CLI.

Dashboard

  • #14750 In the Dashboard, fixed displaying the "Shared Subscriptions" value. Previously, an outdated value may appear.
  • #14638 Added support for using file secrets (i.e.: file://...) to define the Dashboard default password.
  • #14255 Introduced a password expiration mechanism for Dashboard users.
  • #15014 Dashboard security improved. The ability to log into the dashboard is blocked for a period after several unsuccessful attempts. The number of attempts and lock duration can be configured.

Observability

  • #14794 Added the payload_limit parameter to the HTTP API interface for the Log Trace. Previously, the payload print would be truncated if its size exceeded 1024 bytes. Now, this limit is configurable.

  • #14876 End-to-end tracing support for Rule Engine, including tracing for the following entry:

  • Client-published messages triggering Rules

  • Client events and alert events triggering Rules
  • Source-triggered Rules
  • Actions executed by Rules

Limitations: Fallback action tracing is not currently supported.

  • #14723 Add method option to the Prometheus Push Gateway configuration. Before this change, the default value was post. Now, it is put.

The put method is used to replace the metrics of the same job in Pushgateway to avoid the metrics being retained in Pushgateway after being removed from the emqx cluster.

See the PUT method for more details.

  • #14636 The packets.publish.dropped metric has been deprecated and replaced with two new, more meaningful metrics:

  • messages.dropped.quota_exceeded: Triggered when a client exceeds its configured rate limit, such as the allowed number of QoS 0 messages.

  • messages.dropped.receive_maximum: Triggered when the session reaches its Receive Maximum limit while publishing QoS 2 messages.

These new metrics provide more precise insight into why messages are dropped under different conditions.

  • #14540 Introduced configurable latency measurement for authentication and authorization. Metrics are exposed as Prometheus histograms.

  • #14264 Added a timestamp to the crash_dump file to ensure that it is not overwritten by the next crash dump.

  • #15119 Added a high-watermark metric for the session registry table size, showing the peak number of active sessions. This metric is displayed on the Dashboard Overview page to help monitor session resource usage.

  • #15117 Refined the warning log for cinfo authentication expression evaluation failures, making it more concise, and less likely to be mistaken for a crash.

Old log example:

2025-04-25T13:15:59.993395+00:00 [warning] tag: AUTHN, clientid: mqttx_a50058aa, msg: authenticator_error, peername: 127.0.0.1:60842, reason: {case_clause,{error,#{error => #{reason => var_unbound,var_name => <<"cert_common_name">>}, cause => "clientinfo_auth_expression_evaluation_error"}}}, stacktrace: [{emqx_authn_cinfo,do_check,2,[{file,"emqx_authn_cinfo.erl"},{line,94}]},{emqx_authn_cinfo,check,2,[{file,"emqx_authn_cinfo.erl"},{line,82}]},{emqx_authn_chains,authenticate_with_provider,2,...

New log example:

2025-04-25T15:46:50.748732+02:00 [warning] clientid: client1, msg: clientinfo_auth_expression_evaluation_error, peername: 127.0.0.1:53919, reason: #{reason => var_unbound,var_name => <<"cert_common_name">>}

CLI

  • #14691 Added the possibility of filtering which data to be exported to the CLI command emqx ctl data export. It's now possible to specify which root keys from the cluster.hocon file and which table sets are exported, in the same vein as how POST /data/export works.

Configuration File

  • #14647 cluster.hocon backups are now made at a configurable interval. Instead of create a backup for each single config update operation, now we collect several changes before backing the file up, reducing the number of such backups.

Plugin and Extension

  • #14957 Enhanced plugin configuration update handling:
  • Added support for respecting the on_config_changed callback response for plugins. This ensures that when the configuration of a plugin is updated, the plugin’s callback is properly called to handle the change, even for stopped plugins.
  • Introduced a new method for updating plugin configurations that respects the result of the on_config_changed callback.

Gateway

  • #14017 Support for parsing customized types of InfoReport data messages in the GB/T 32960 gateway.

MQTT over QUIC

  • #14431 Switched to newer QUIC stack: quicer 0.2.3:

  • msquic 2.3.8 + patches

  • Advance resource management

  • Prepared to support more dynamic config changes on the listeners

System Upgrade

  • #14639 EMQX is now released on Erlang/OTP 27.

Bug Fixes

Core MQTT Functionalities

  • #14707 Fixed an issue where, in strict_mode, PUBLISH packets with QoS 2 and the DUP flag set were incorrectly considered invalid packets.

  • #14192 Allowed will messages to be sent by the clients that disconnect because of authentication/authorization expiration. Previously, such clients could not send a will message because the sending occurred just after the authorization expiration, so the message could not pass the authorization rules.

  • #14122 Fixed handling of PUBACK and PUBREC/PUBCOMP when the published message has QoS 2 and 1, repectively.

Prior to this fix, the broker would accept PUBACK and PUBREC/PUBCOMP packets from clients referencing packet identifiers that corresponded to messages with QoS 2 and 1, respectively. Now, the broker will disconnect clients that behave like this.

  • #15106 Fixed a bug where duplicated clientid values were being returned by the GET api/v5/clients_v2 API. This issue occurred due to the accidental resurrection of chaninfo events, causing unexpected client data duplication. The fix ensures that such events do not inadvertently affect the client list, resolving the issue where clients appeared as duplicated on the client page.

  • #14906 Updated Mria to 0.8.12.1 to eliminate occasional warnings caused by unexpected exit signals.

2025-01-10T20:00:00+00:00 [warning] clientid: C1, msg: emqx_session_mem_unknown_message, message: {'EXIT',<0.123456.0>,normal}

  • #15084 Client attributes zone and listener can be used as various string function input.

Previously functions like regex_match would raise exception because zone and listener are internally atoms.

Installation

  • #14624 Fixed macOS release package dynamic linking openssl.e

EMQX zip package may fail to start on macOS because quicer application dynamic links to sys installed openssl which is not signed by EMQX build process.

Now we change to disabled dynamic linking as the OTP we shipped on macOS also disabled dynamic linking of openssl.

REST API

  • #14771 Fixed an issue where the number of results that the GET /clients_v2 HTTP API returned could exceed the requested limit.

Note: while performing a rolling upgrade, this API may not list all existing clients until all nodes are migrated. As a workaround, if HTTP API requests are issued to old core nodes, all clients can be listed before all nodes are fully upgraded.

  • #14182 Previously, if a delayed message was published via the POST /publish HTTP API, a 202 reponse with the reason code 16 ("no matching subscribers") would be returned. Now, a 200 response is sent along with the message identifier.

MQTT Durable Sessions

  • #14674 Limit number and size of RocksDB info log files created by EMQX durable storage.
  • #14498 Improved performance of durable sessions:
  • Idle durable sessions no longer consume CPU cycles.
  • Fixed QoS upgrade feature: subscribers will no longer receive messages with QoS higher than QoS of the subscription when feature is enabled.

  • #14933 Resolved a rare edge case where a Durable Storage backed by DS Raft could be assigned to storage sites that had left the cluster long ago.

Authentication and Authorization

  • #14777 Fixed settings update for JWT authentication. Previously, some fields may be not updated correctly for a configuration with external JWKS endpoint.

  • #14556 Fixed rarely possible false positive authentication while the node is starting or shutting down.

  • #15059 Fixed the reaction to updating the Redis authentication config with invalid values.

Previously, the authenticator could crash and stop being applied during authentication. Now, proper errors are provided to the user and the update is denied.

  • #14303 Resolved an issue with broken scram:http authentication. The request sent to the HTTP connector was malformed, causing authentication failures.

Clustering

  • #14778 Fixed a bug where, if a running node had broken symlinks in its data/certs or data/authz directories, another node would fail to join it.
  • #14936 Resolved an issue where, in rare cases, the global routing table could indefinitely retain routing information for nodes that had long left the cluster.
  • #14977 Fixed emqx ctl conf cluster_sync status command node display order. Previously, the node name for new/old config was printed in the other way around.

Cluster Linking

  • #15067 Fixed a couple of issues with Cluster Linking Route Replication.
  • Replication process may enter erratic reconnect loop when the Cluster Link is misconfigured on local or remote side, which will hinder replication once misconfiguration is resolved.
  • Replication process may crash during attempts to close non-existing MQTT client connection.
  • Replication boostrapping may crash if shared subscriptions are present in the routing table.

Rule Engine

  • #14849 Removed an spurious field (event_type) from POST /rule_test responses. This was an internal field that doesn't actually appear in real events, so its presence in rule test outputs could be confusing.
  • #15056 For MQTT messages whose payload is a JSON list object, it is no longer necessary to explicitly decode the payload in the foreach statement.

Smart Data Hub

  • #14988 Fixed an issue where Schema Validation or Message Transformation configurations could be imported before Schema Registry when restoring a backup, leading to validation errors.

Data Integration

  • #14716 Adding and removing Actions/Sources is now done asynchronously outside of configuration changes. This means that the possibility of configuration and resource states diverging due to timeouts no longer can occur.

  • #14519 When (re)starting a node that's already configured with some Sources, it could happen that some transient warning logs could be logged because metrics were missing if said Sources started to receive traffic too soon. This has been fixed.

Example of such logs:

2025-01-08T07:48:36.421822+00:00 [warning] tag: RESOURCE, msg: handle_resource_metrics_failed, reason: {badkey,received}, stacktrace: ..., event: received, kind: error, hint: transient failures may occur when restarting a resource, resource_id: <<"source:mqtt:tset:connector:mqtt:test">>

  • #14992 Fixed a potential resource leak due to rare race conditions when testing connectivity of Connectors.

  • #15000 Fixed an issue where loading a configuration via CLI or HTTP API could cause instabilities in Connectors, Actions and/or Sources.

  • #15010 Previously, disabling any Connector could take about 5 to 10 s, even when it was healthy. This has been fixed. Note that some Connectors still naturally require time to disable, especially when they have Actions and when they are unhealthy.

  • #15051 Enhance the TDengine connector by adding parameter validation and updating the driver version to provide clearer error messages.

  • #15012 Fixed an issue where the publish_confirmation_timeout parameter of RabbitMQ Actions were being multiplied by 1000.

  • #14989 Reduced the number of API calls that Kinesis Connection and Action do when (re)starting and during health checks.

Previously, upon (re)starting the Connector, it would perform one ListStreams request for each worker in its connection pool. Additionally, each periodic health check would do ListStreams for each worker. The Action health check would do DescribeStream for each connection worker in the pool.

Now, the Connector no longer performs the initial ListStreams upon (re)starting. Both Connector and Action attempt to check if at least one worker has a healthy response from their respective API requests: the request is attempted by each worker serially, and the Connector or Action is considered connected upon the first successful response received. Thus, in the best case scenario, each Connector and each Action will do 1 API request each per health check, regardless of pool sizea. In the worst case scenario, each worker in the pool might still perform one request each, if they fail to receive a sucessful response.

  • #14767 Kafka producer now smoothly handles Kafka topic re-creation with fewer partitions. Previously, the lost partition producers may linger behind to retry and write large amount of error logs.

  • #14121 Deprecated the health_check_topic configuration for Kafka Consumer Connector to avoid further confusion. This parameter was never actually used for this connector type.

  • #15116 The Kafka connector now allows topic_authorization_failed as a valid response during health check probing. This change improved compatibility with Kafka services that enforce ACLs, where access to the default health-check topic may be restricted.

Administration

  • #14931 The configuration mqtt.max_qos_allowed is now used as the granted subscription QoS and returned as the reason code in the SUBACK packet. Previously, the reason code in SUBACK packets was hard-coded to the subscription QoS instead of dynamically reflecting the granted QoS.
  • #14975 Fixed an issue preventing on-the-fly updates to certain TLS listener options, requiring a disable-enable cycle for changes to take effect.
  • #15037 Fixed rate limiting for dynamicalley created zones. Previously, the rate-limiting was not applied if a zone was created after the EMQX node was started.

Configuration File

  • #15087 Fixed an issue with hocon library in which, if one had any string one-liner field that ended in a lone backslash, the configuration file would fail to be parsed later.

Plugin and Extention

  • #15073 Added a validator for the server URL in the exhook configuration. This ensures that only valid URLs can be saved. Invalid URLs will now trigger an error and prevent being saved, which helps avoid issues during the import process, where previously invalid URLs could be accepted.

  • #14774 Resolved plugin related issues. Fixed a retrieval issue with the plugin configuration file from cluster nodes when initiating the plugin without an existing configuration file.

  • #14826 Fixed the issue where the Exhook server's return of "IGNORE" was not taking effect.

  • #15018 Fixed a bug with Exhook in which attemtping to import an invalid exhook configuration via the CLI would result in a crash with a badarg error.

  • #15108 ExHook now includes a built-in gRPC health check mechanism, ensuring that the connection status accurately reflects the actual availability of the external hook server.

This fix addresses issues where the status could remain stale after the server was stopped for an extended time. Automatic reconnection is supported if enabled in the configuration.

MQTT over QUIC

  • #14775 QUIC Listener: Fixed issue where zone configurations are not applied after a config reload.

Breaking Changes

  • #14865 Dropped old LDAP authentication config layout (deprecated since v5.4). Move password_attribute and is_superuser_attribute under the method block: hcl method { type = hash password_attribute = "userPassword" is_superuser_attribute = "isSuperuser" }

  • #14765 Added extra validation for using Named Instances in SQL Server Connector. Previously, we could not infer when the user furnished an explicit port for SQL Server, and always added the default port if not explicitly defined.

For Named Instances, we need to explicitly define a port to connect to when connecting with the ODBC driver. And the driver happily connects to whatever instance is running on that port, completely ignoring the given Instance Name, if any.

Now, we impose that the port is to be explicitly defined when an instance name is given, and we also attempt to infer differences between desired and connected instance names during health checks.

  • #14773 Rate limiting configuration options have been changed.
  • This change is incompatible with versions prior to 5.1.0
  • This change is also incompatible with manually modified limiter configurations that use structures from versions prior to 5.1.0
  • The undocumented endpoint /configs/limiter has been removed

  • #14703 Changed the maximum allowed value for force_shutdown.max_heap_size to 128GB.

  • #14957 The way plugin configurations are updated has changed. The system now respects the result of the on_config_changed callback when updating a plugin's configuration. This change only affects new configuration updates made through the Dashboard. The result of the on_config_changed callback is still ignored for configurations that have already been stored in the cluster.

Additionally, plugin apps are now loaded during plugin installation to ensure the on_config_changed callback is called even for stopped plugins.

Source: README.md, updated 2025-05-02