Skip to content

System Topics and Client Event Subscriptions

EMQX publishes client connection, disconnection, and subscription events to system topics prefixed with $SYS/, for example:

$SYS/brokers/${node}/clients/${clientid}/connected

$SYS system topics contain Broker node-level information and are intended for internal Broker observability, compatibility, and operational diagnostics. To subscribe to system topics in EMQX Cloud, you must add the appropriate authorization in the default ACL rules, for example, allowing a username such as emqx to subscribe to $SYS/#.

For production business integrations, the recommended approach is to use EMQX Cloud Data Integration to capture client events, then forward them to business topics using the Republish action. EMQX Cloud supports filtering and transforming event data with rule SQL before republishing the results to any MQTT topic.

This page explains how system topics work in EMQX Cloud and how to use Data Integration to forward client events to business topics for downstream consumption.

When to Use Each Approach

System topics are suitable for Broker observability, compatibility adapters, and operational diagnostics. If your goal is to capture client connection, disconnection, or subscription events and integrate them into a production system, Data Integration is the better choice.

Aspect$SYS System TopicsData Integration + Republish
Use caseBroker observability, diagnostics, compatibilityBusiness integration, event forwarding
Topic structureContains ${node}, tied to internal Broker node namesRepublish to stable, custom business topics
Data processingClients parse raw messages themselvesFilter, transform, and mask data centrally in rule SQL
Security boundaryMay expose internal Broker node informationSet independent access control on business topics
ExtensibilitySubscription-only observationForward to MQTT topics or external systems simultaneously

System Topics

System topics follow the format $SYS/brokers/${node}/..., where ${node} is the Broker node name (for example, emqx@127.0.0.1).

Client Event Topics

The following system topics are available for client state events:

EventSystem Topic
Client connected$SYS/brokers/${node}/clients/${clientid}/connected
Client disconnected$SYS/brokers/${node}/clients/${clientid}/disconnected
Client subscribed$SYS/brokers/${node}/clients/${clientid}/subscribed
Client unsubscribed$SYS/brokers/${node}/clients/${clientid}/unsubscribed

Note

All four event types are enabled by default. To subscribe to them, add the appropriate authorization in the default ACL rules, for example, allowing a specific username to subscribe to $SYS/#.

Data Integration provides built-in event topics prefixed with $events/. These are more stable than system topics, are not tied to node names, and support data processing in rule SQL before forwarding to custom business topics. By default, clients cannot subscribe to these event topics directly. They must be handled and forwarded through a Data Integration rule. For a full reference of available fields for each event, see SQL Data Sources and Fields — MQTT Events.

System Topics vs. Data Integration Event Topics

Event$SYS System TopicData Integration Event Topic
Client connected$SYS/brokers/${node}/clients/${clientid}/connected$events/client/connected
Client disconnected$SYS/brokers/${node}/clients/${clientid}/disconnected$events/client/disconnected
Client subscribed$SYS/brokers/${node}/clients/${clientid}/subscribed$events/session/subscribed
Client unsubscribed$SYS/brokers/${node}/clients/${clientid}/unsubscribed$events/session/unsubscribed

Note

New rules should use the namespaced event topics such as $events/client/connected and $events/session/subscribed. Legacy event topic formats remain supported but are not recommended for new configurations.

Forward events to business topics through a Data Integration rule, and have business clients subscribe to those topics rather than depending on system topics directly:

$events/client/#  or  $events/session/#
  → Data Integration rule SQL (filter, transform)
  → Republish action
  → Business topic (e.g., iot/events/client/connected)
  → Business client subscribes

Configure Data Integration to Forward Client Events

The following examples show how to configure a rule and Republish action for each of the four client event types.

Client Connected

Event topic

$events/client/connected

Rule SQL

sql
SELECT
  clientid,
  username,
  peername,
  proto_name,
  proto_ver,
  keepalive,
  clean_start,
  expiry_interval,
  connected_at,
  timestamp,
  node
FROM
  "$events/client/connected"

Suggested republish topic

iot/events/client/connected

Payload template

json
{
  "event": "client.connected",
  "clientid": "${clientid}",
  "username": "${username}",
  "peername": "${peername}",
  "proto_name": "${proto_name}",
  "proto_ver": ${proto_ver},
  "keepalive": ${keepalive},
  "clean_start": ${clean_start},
  "expiry_interval": ${expiry_interval},
  "connected_at": ${connected_at},
  "timestamp": ${timestamp},
  "node": "${node}"
}

Client Disconnected

Event topic

$events/client/disconnected

Rule SQL

sql
SELECT
  clientid,
  username,
  reason,
  peername,
  connected_at,
  disconnected_at,
  timestamp,
  node
FROM
  "$events/client/disconnected"

Suggested republish topic

iot/events/client/disconnected

Payload template

json
{
  "event": "client.disconnected",
  "clientid": "${clientid}",
  "username": "${username}",
  "reason": "${reason}",
  "peername": "${peername}",
  "connected_at": ${connected_at},
  "disconnected_at": ${disconnected_at},
  "timestamp": ${timestamp},
  "node": "${node}"
}

Client Subscribed

Event topic

$events/session/subscribed

Rule SQL

sql
SELECT
  clientid,
  username,
  topic,
  qos,
  sub_props,
  timestamp,
  node
FROM
  "$events/session/subscribed"

Suggested republish topic

iot/events/session/subscribed

Payload template

json
{
  "event": "session.subscribed",
  "clientid": "${clientid}",
  "username": "${username}",
  "topic": "${topic}",
  "qos": ${qos},
  "sub_props": ${sub_props},
  "timestamp": ${timestamp},
  "node": "${node}"
}

Client Unsubscribed

Event topic

$events/session/unsubscribed

Rule SQL

sql
SELECT
  clientid,
  username,
  topic,
  qos,
  unsub_props,
  timestamp,
  node
FROM
  "$events/session/unsubscribed"

Suggested republish topic

iot/events/session/unsubscribed

Payload template

json
{
  "event": "session.unsubscribed",
  "clientid": "${clientid}",
  "username": "${username}",
  "topic": "${topic}",
  "qos": ${qos},
  "unsub_props": ${unsub_props},
  "timestamp": ${timestamp},
  "node": "${node}"
}

Create a Data Integration Rule

Follow these steps in the EMQX Cloud Console to create a rule and add a Republish action:

  1. Go to the Data Integration page of your deployment.
  2. Under Data Forwarding, select Republish and click Create.
  3. Enter the rule SQL in the SQL editor.
  4. Click Next and add a Republish action.
  5. Set the target business topic, Payload template, QoS, Retain flag, and any other parameters.
  6. Click Confirm to save, then use the SQL test tool to verify the rule behaves as expected.

TIP

To prevent a republished message from triggering the same rule again, enable Direct Dispatch in the action configuration. With Direct Dispatch enabled, messages are delivered directly to subscribers without passing through the rule engine, avoiding loop triggers.

Best Practices

  • Use $events/client/# and $events/session/# as the unified source for client connection, disconnection, subscription, and unsubscription events.
  • Use Data Integration rule SQL to filter, transform, and mask event data centrally.
  • Republish events to stable business topics such as iot/events/client/+ and iot/events/session/+, so business systems do not depend directly on $SYS/brokers/${node}/... internal topic structures.
  • Business clients should subscribe only to business topics. Apply independent ACL rules to those topics to enforce access control and isolation.
  • Write events to external systems as needed for auditing, querying, monitoring, and alerting.