Download Latest Version EMQX Enterprise (LTS) 6.3.2 source code.zip (16.0 MB) Google Add to Preferred Sources
Home / 6.3.2
Name Modified Size InfoDownloads / Week
Parent folder
EMQX Enterprise (LTS) 6.3.2 source code.tar.gz 2026-10-16 13.7 MB
EMQX Enterprise (LTS) 6.3.2 source code.zip 2026-10-16 16.0 MB
EMQX Enterprise LTS 6.3.2 source code.tar.gz 2026-10-16 13.7 MB
EMQX Enterprise LTS 6.3.2 source code.zip 2026-10-16 16.0 MB
README.md 2026-10-16 26.9 kB
Totals: 5 Items   59.3 MB 5

Download

Ubuntu / Debian

OS Arch Package Tarball
ubuntu24.04 amd64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
ubuntu24.04 arm64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
ubuntu22.04 amd64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
ubuntu22.04 arm64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
debian13 amd64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
debian13 arm64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
debian12 amd64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
debian12 arm64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
debian11 amd64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)
debian11 arm64 .deb (sha256) .tar.gz (www.emqx.com) (sha256)

RHEL / Rocky / Amazon Linux

OS Arch Package Tarball
el10 amd64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)
el10 arm64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)
el9 amd64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)
el9 arm64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)
el8 amd64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)
el8 arm64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)
amzn2023 amd64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)
amzn2023 arm64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)
el7 amd64 .rpm (sha256) .tar.gz (www.emqx.com) (sha256)

macOS

OS Arch Package
macos14 arm64 .zip (sha256)
macos15 arm64 .zip (sha256)
macos26 arm64 .zip (sha256)

Plugins

Plugin Version Package
emqx_acme 0.2.0 .tar.gz (www.emqx.com) (sha256)
emqx_agent 1.0.0 .tar.gz (www.emqx.com) (sha256)
emqx_backup_sync 0.1.3 .tar.gz (www.emqx.com) (sha256)
emqx_bridge_mqtt_dq 0.5.2 .tar.gz (www.emqx.com) (sha256)
emqx_maptabs 0.1.2 .tar.gz (www.emqx.com) (sha256)
emqx_offline_messages 2.0.1 .tar.gz (www.emqx.com) (sha256)
emqx_relup 1.0.2 .tar.gz (www.emqx.com) (sha256)
emqx_sync_request 0.1.2 .tar.gz (www.emqx.com) (sha256)
emqx_unsgov 0.1.4 .tar.gz (www.emqx.com) (sha256)
emqx_username_quota 1.2.3 .tar.gz (www.emqx.com) (sha256)

Summary

6.3.2 is a maintenance release focused on resource usage and rolling-upgrade reliability.

  • Lower memory per connection and per client. Idle connections hibernate after 5 s (mqtt.hibernate_after), rate-limiter and queue state is allocated only when needed, and the node-local client tables store less per client — about 5 KB saved per idle connection plus several hundred bytes per client in the tables, and about 110 MB per million subscribing clients. REST API responses and hook arguments are unchanged.
  • Lower CPU per packet. Hooks are invoked directly by name, packet and resource metrics cost fewer lookups, SUBSCRIBE handling does one table write instead of two, the socket backend makes fewer receive system calls, and the broker now starts only as many schedulers as its CPU quota allows (docker --cpus, Kubernetes limits), which removes about 30% CPU overhead in capped containers.
  • tcp_backend defaults back to gen_tcp. 6.3.0 switched the default TCP listener backend to socket; 6.3.2 restores gen_tcp so that every v6 release behaves the same. This is a consistency decision, not a verdict on the backend: in almost all our benchmarks the socket backend uses less CPU than gen_tcp, but it holds slightly more memory per connection, so a large idle connection count can need more RAM. The socket backend stays available with tcp_backend = socket and is planned to become the default again in v7. A listener that relied on the default switches back to gen_tcp and is restarted on upgrade; a listener that sets tcp_backend explicitly is unaffected.
  • Fixes for 6.3.0/6.3.1 regressions. The QoS 1 burst slowdown on the socket backend, QoS 0 messages stalling behind a full inflight window, and docker run --user root are fixed.
  • Rolling upgrades. MQTT-SN session takeover now works between nodes of different versions, and node evacuation from older nodes completes again.

See the full list below.

Enhancements

Core MQTT Functionalities

  • #19438 On uncongested connections, in-memory sessions now continue draining queued QoS 0 messages optimistically, even when earlier QoS 1/2 messages must wait for acknowledgments. This includes draining after congestion clears or an existing session resumes. With topic priorities enabled, draining QoS 0 messages may still stop earlier.

Performance

This release reduces the memory each MQTT connection holds and the CPU each packet costs.

  • Memory per connection. A connection now hibernates after mqtt.hibernate_after, which defaults to 5 seconds without traffic. Hibernation shrinks the process heap to the data still in use and releases about 5 KB per connection. Before, TCP and TLS connections hibernated only after mqtt.idle_timeout (15 seconds by default) and WebSocket connections stayed awake after their first packet. Set mqtt.hibernate_after = infinity to keep connections awake, and raise the value when clients send at intervals close to it, because each hibernation costs one garbage collection and the heap grows again on wake-up (#19092). A connection whose zone and listener configure no message, byte or subscribe rate limit no longer allocates rate-limiter state; a limit configured later still applies to established connections (#19181). A session with no queued messages, such as a publish-only client or a subscriber that keeps up with delivery, saves 48 bytes (#19262).

  • Memory per client in the node-local tables. The client information table no longer stores a client's will message, its CONNECT properties or its subscription list, so each entry has a fixed size and is no longer rewritten on every SUBACK and UNSUBACK (#19306). It also drops the sockinfo map and the peerhost, peerport, peername and sockport values that conninfo already carries, about 100 bytes per connection (#19263), and the per-client statistics whose value is 0, about 145 bytes per idle client (#19303). Clients that subscribe over TCP, TLS or WebSocket no longer get a row in the subscriber-id table, about 110 bytes per client and about 110 MB for one million clients (#19245).

REST API responses, CLI output and the arguments passed to hook callbacks are unchanged. Plugins that read the client information table directly, through emqx_cm:get_chan_info/1,2, emqx_cm:lookup_client/1, emqx_mgmt:lookup_client/2, emqx_channel:info/1 or emqx_connection:info/1, no longer see will_msg, conninfo.conn_props or session.subscriptions in the returned map. Use emqx_broker:subscriptions/1 for a client's subscriptions, the client.connected hook for its CONNECT properties, or emqx_channel:info/2 to read a single attribute.

  • CPU per packet. Hooks are now invoked directly by name during message processing and client lifecycle operations (#19527), metric updates and reads need fewer lookups (#19536), and the received and sent packet counters are updated with one counter lookup per packet instead of one per counter (#19516). On TCP listeners with tcp_backend = socket, a connection makes fewer receive system calls per incoming packet; for packets up to 1 KB, broker CPU per received QoS 0 PUBLISH packet dropped by about 7%, and for larger packets it is the same or lower (#19528).

  • SUBSCRIBE path. After each SUBACK and UNSUBACK the broker updates the client's table entry in one write instead of two, which lowers SUBSCRIBE latency under a high rate of new subscribing connections (#19532). With the retainer enabled, a subscription to a topic filter without wildcards now checks for a retained message before it prepares delivery, and does no further retained-message work when there is none (#19545). mria 1.0.2 runs a cluster-table write in a helper process only when the calling process has 100 or more messages queued, instead of 10; under a high rate of new subscriptions the route-storing workers crossed the old limit on one write in ten and waited for the helper each time (#19555). The emqx ctl subscriptions show <ClientId> command no longer scans all subscriptions on the node to find those of one client (#19245).

  • TLS connections. OTP is upgraded to 28.4.1-7 (builder 6.2-3). Each TLS connection uses less memory: the per-connection ETS table for shared socket options is gone, and idle TLS 1.3 connections release their cipher state. A TLS handshake no longer makes two calls to the Erlang file server to resolve an absolute cacertfile path, which removes a file-server backlog under a burst of TLS connections (#19563).

  • Startup time. The nodetool helper included in release packages is precompiled (#19183).

Bug Fixes

Core MQTT Functionalities

  • #19489 Changed the default tcp_backend for MQTT TCP listeners back to gen_tcp.

6.3.0 made socket the default on Unix and Linux. It uses more memory per connection, so the default returns to gen_tcp while that is addressed. So far only tests that open connections without message traffic have measured that cost; tests with message traffic have not. socket is planned to become the default again in v7.

The socket backend is unchanged and still available on Unix and Linux with tcp_backend = socket. A listener that sets tcp_backend explicitly is unaffected. A listener that relies on the default switches back to gen_tcp, which restarts it and closes its active connections on upgrade.

  • #19298 Fixed a performance regression introduced in EMQX 6.3.0 that caused high CPU usage and slow message delivery during large QoS 1 message bursts on TCP listeners using the socket backend. Also improved burst throughput by batching outgoing messages.

  • #19326 Revised message delivery so that a full inflight window is no longer treated as a connection congestion signal. QoS 0 messages can now be delivered while the inflight window is full, reducing unnecessary queueing and message drops while preserving ordering for each topic and QoS level.

Also fixed QoS 1 and QoS 2 message reordering under delivery rate limits, and prevented queued messages from consuming delivery quota before they are sent.

  • #19351 Upgraded esockd from 5.17.4 to 5.17.8 to fix several listener issues:

  • Fixed severely reduced TCP throughput on high-MTU links when using the socket backend with a small tcp_options.recbuf value.

  • Fixed PROXY Protocol v2 headers with zero-length proxy information consuming MQTT data, and rejected truncated IPv4/IPv6 address information without crashing.
  • Incomplete PROXY Protocol v1 headers are now rejected by the socket backend connections.
  • Corrected listener option merging and socket tuning, and prevented acceptor crashes when updating uninitialized counters.

  • #19144 Fixed an issue where the session registry cleanup process stopped when a client disconnected while the cleanup was running. The cleanup now continues past the disconnected client and keeps removing stale registrations.

  • #19316 Fixed a leak of rate-limiter bucket entries in persistent_term when the limiter registry was restarted or the node was shut down without running the registry's cleanup.

Observability

  • #19561 Fixed a log formatter crash when a log handler sets payload_encode = hidden. Before this fix, a debug log event that carried a term field, for example the data field of the Cluster Linking recv_data event, was replaced by a FORMATTER CRASH report. Now the field is redacted as Encoded(hidden)=****** and the log entry is written normally.

Gateways

  • #19422 Fixed MQTT-SN session takeover failures in mixed-version clusters, such as during rolling upgrades to EMQX 6.3.0, 6.3.1, or 6.3.2 from earlier releases. Reconnecting or waking up on a node running a different version could fail or crash the client channel, preventing session resumption and pending-message delivery.

  • #19459 Fixed the MQTT-SN gateway omitting the DUP and RETAIN flags from outgoing PUBLISH packets. Clients can now identify retransmitted messages and retained messages delivered on subscription.

  • #19393 Fixed an error log on every QoS 1 and QoS 2 delivery to a gateway client that resumed its session.

When message queues or streams were in use, delivering such a message raised an exception inside a hook callback. EMQX caught it and logged hook_callback_exception at error level. Delivery itself was not affected. Gateway channels that resume a session, such as an MQTT-SN client waking up from sleep, do not run a session lifecycle hook, so the channel metadata the callback required was never set for them.

Access Control

  • #19282 Fixed HTTP authentication with hostname_resolution = dynamic rejecting responses whose Content-Type header name is not all lowercase, for example Content-Type: application/json. Such a response is now accepted. Previously, the authentication backend reported unsupported_content_type and the client could not connect.

Data Integration

  • #19313 Improved the detection of unresponsive connections in HTTP-based connectors, such as HTTP Server, GCP PubSub Producer, Couchbase and Snowflake.

Before this fix, a connection with requests waiting for a response was reconnected only after the full request timeout (resource_opts.request_ttl) plus max_inactive had passed. With a large request_ttl this took a long time. With request_ttl = infinity, the connection was never reconnected.

Now a connection is reconnected when no request has been sent on it for 60 seconds while requests still wait for a response, or for max_inactive when that is longer. The default settings (request_ttl 45 seconds, max_inactive 10 seconds) are not affected.

This changes the behavior of connectors configured with a request_ttl above about 50 seconds. A response that takes longer than 60 seconds can now be interrupted by a reconnect. If the remote service is expected to take longer than 60 seconds to respond, set max_inactive to at least the slowest expected response time.

Node and Cluster

  • #19580 Fixed a rolling upgrade that could stop with client sessions left on an old node. Nodes that run 5.8 to 5.10, 6.0.0 to 6.0.3, 6.1.0 to 6.1.4, 6.2.0 to 6.2.3 or 6.3.0 move sessions to other nodes during node evacuation with a call that 6.0.4, 6.1.5 and 6.3.1 no longer answered. The old node then kept the sessions and tried again without end, so the evacuation did not complete. The new node answers this call again.

  • #19578 Fixed a crash when transferring previously evacuated sessions from older EMQX nodes during rolling upgrades if the sessions lacked listener metadata.

  • #19444 Fixed the number of Erlang schedulers when EMQX runs under a CPU quota, such as docker run --cpus or a Kubernetes CPU limit.

Since 6.3.0, EMQX started one scheduler for each CPU core of the host, even when the container could use only a few of them. The schedulers then competed for the CPU quota, and the broker used about 30% more CPU for the same message rate. EMQX now starts as many schedulers as the CPU quota allows. To set the number explicitly, use node.schedulers.

  • #19160 Fix the following crash in mria application that occurs when a core node joins or leaves the cluster:

Reason: {badarg,[{ets,select,[gproc,[{{{{n,l,{mria_rlog_replica,route_shard_m,'$1'}},n},'$2','_'},[],[{{'$1','$2'}}]]],[{error_info,#{cause => id...

This fix removes gproc dependency of mria application from the list of business-level applications that reboot when the node changes the cluster.

Packaging

  • #19141 Restored the root entry in the docker image's /etc/passwd, so docker run --user root works again. It was dropped in 6.3.1 when the image moved to a hardened base, and only the numeric form --user 0:0 worked.
Source: README.md, updated 2026-10-16