# Capture Client Connection and Disconnection Event Topic Messages via Data Integration

**Client connection and disconnection event topics** are system topics used by EMQX to notify changes in client connection status, including `$events/client_connected` and `$events/client_disconnected`. Although normal clients cannot subscribe to these topics directly, you can capture them through the Rule Engine for further processing—for example, writing data to a database, forwarding it to other topics, or performing real-time monitoring and analysis.

Because EMQX functions as an MQTT Broker rather than a storage service, and for security and privacy reasons, it does not retain historical client status records or debug-level event logs by default. Therefore, we recommend configuring **Data Integration rules** for client connection and disconnection event topics in your deployment to enable real-time tracking of device connection status and the preservation of essential activity records, which are valuable for troubleshooting and auditing.

This page introduces the use cases for client connection and disconnection event topics, demonstrates how to capture these messages using the Rule Engine, and uses [MQTTX Desktop](https://mqttx.app/) to simulate a client receiving event topic messages.

## Key Use Cases

Client connection and disconnection event topics can be used in multiple scenarios, including:

  - **Recording device connection history**: Log events to an external database to track device connection history and behavior patterns, supporting later analysis and reporting.
  - **Monitoring device online status and activity**: Gain real-time insights into device connectivity and client activity, helping business systems make dynamic adjustments or policy decisions.
  - **Troubleshooting disconnections**: By analyzing the reasons and timing of disconnection events, the technical support team can quickly identify and resolve unexpected disconnections.
  - **Security auditing and access behavior tracking**: Store events in a log platform for access tracking, security investigations, and compliance audits.

## Trigger Conditions and Key Fields

### Client Connected Event ("$events/client\_connected")

  - **Trigger**: Triggered when a client successfully connects.
  - **Key fields**:

| Field           | Explanation                                                    |
|-----------------|----------------------------------------------------------------|
| clientid        | The connected client’s ID                                      |
| username        | The username used for the connection                           |
| peername        | Client IP address and port                                     |
| keepalive       | MQTT keepalive interval (heartbeat frequency from client to broker) |
| clean_start     | MQTT clean_start (Whether the client is starting a clean session) |
| expiry_interval | MQTT session expiry interval (how long the session is kept after disconnection) |
| connected_at    | Timestamp of when the connection was established (Unit: ms)    |

### Client Disconnected Event ("$events/client\_disconnected")

  - **Trigger**: Triggered when a client disconnects.
  - **Key fields**:

| Field           | Explanation                                                    |
|-----------------|----------------------------------------------------------------|
| reason          | Reason for the disconnection                                   |
| clientid        | The disconnected client’s ID                                   |
| username        | The username used for the connection                           |
| peername        | Client IP address and port                                     |
| disconnected_at | Timestamp of when the client disconnected (Unit: ms)           |

::: tip

For the full list of event topic fields, refer to the official documentation: [Event Topic List](../rule_engine/rule_engine_events.md#event-topic-list)

:::

## Analysis of Disconnection Scenarios

The `reason` field in the client disconnected event topic provides the specific cause of a disconnection, which helps in understanding connection issues and optimizing client connection logic. Below is a detailed analysis of all disconnection reasons:

| Reason Code | Explanation |
| :--- | :--- |
| normal | The client actively disconnected. This is the standard scenario, where the client ends the session following the normal MQTT protocol flow. |
| kicked | The client was disconnected by the server, usually because an administrator actively terminated the session via the API or console. |
| keepalive_timeout | Triggered when a client fails to send a heartbeat (Pingreq) to EMQX within the specified Keepalive interval. Common causes include:<br>1. **Network jitter**: Unstable network between the client and EMQX causes lost, delayed, or dropped heartbeat messages.<br>2. **Client heartbeat issues**: The client’s heartbeat mechanism is faulty and does not send MQTT heartbeats within the required interval.<br>For more details, refer to the [Keepalive documentation](https://www.emqx.com/en/blog/mqtt-keep-alive). |
| not_authorized | Triggered when a client fails authentication or lacks sufficient permissions. Common causes include:<br>1. **Authentication failure**: The client provides invalid MQTT credentials.<br>2. **Insufficient permissions**: When `acl_nomatch = disconnect` (default), the client attempts a publish/subscribe operation without proper access rights. |
| tcp_closed | The remote side closed the TCP connection. This often occurs when a client crashes or there is a network issue, bypassing the MQTT DISCONNECT packet interaction. Examples include forcibly closing the client application, network interruption by the ISP, or abrupt device network disconnections. |
| internal_error | Occurs due to malformed packets or other unknown errors. Resolving this typically requires inspecting packet contents, checking server logs, or contacting the EMQX technical support team. |
| discarded | Occurs when two clients use the same ClientID with `clean_start = true`. EMQX discards the existing session, establishes a new session, and disconnects the old client.<br> `clean_start = true` indicates the client wants a fresh session on each connection. When a new client uses the same ClientID, EMQX treats it as a new session, deletes the old subscriptions and message queues, and replaces the old session with the new connection. |
| takenover | Occurs when two clients use the same ClientID with `clean_start = false`. EMQX allows the new client to take over the existing session and disconnects the old client.<br> `clean_start = false` indicates the client wants to reuse the existing session. When a new client connects with the same ClientID, EMQX transfers the old session to the new client while disconnecting the previous client. |

::: tip

Below are two common scenarios of ClientID conflict disconnections:

1.  **ClientID conflict with repeated session takeover**: When multiple different clients use the same ClientID and have automatic reconnection enabled, the new connection repeatedly kicks out the old session, creating a loop of reconnections. In this case, the client’s IP and port often change.

    **Recommendation**: Assign a unique ClientID to each client.

2.  **Repeated client reconnections**: If a client session still exists but the client does not recognize it as active, the client process may repeatedly send new MQTT CONNECT packets, which can override the existing session. In this scenario, the IP usually remains the same, while the port may change; on some IoT network modules, both IP and port can change.

    **Recommendation**: Review and optimize the client connection logic.
:::

## Configure Data Integration to Capture Event Topic Messages

In practice, event topics are typically handled in one of two ways:

1.  **Message republishing**: Republishes event topic messages to other MQTT topics. This approach is lightweight, real-time, and fully compatible with the native MQTT ecosystem, making it ideal for quickly consuming and processing events within the system.
2.  **Forwarding to external services**: Sends event topic messages to external systems such as databases, message queues, or HTTP services. This approach enables integration with a variety of external systems and supports real-time responses and persistent processing.

This page demonstrates message republishing and forwarding to HTTP services. For other methods, such as forwarding to different databases or external systems, see the official documentation: [EMQX Cloud Data Integration](../data_integration/introduction.md).

### Message Republish

This section demonstrates how to republish client connection and disconnection event topic messages to other topics.

#### Create Rule and Action

1.  In the **Data Integration** page, under the **Data Forward** category, click **Republish**. If you have existing connectors, click **New Connector**, then select **Republish** under the **Data Forward** category.
2.  Define the Rule SQL in the **SQL Editor**. To track client disconnection events, you can use the following SQL example:
```sql
SELECT
    clientid, 
    username, 
    reason, 
    disconnected_at
FROM
    "$events/client_disconnected"
```

3.  Click **Next** to add an action.
4.  In the **Create Action** step, configure the following information:
      - **Connector**: Use the default option Republish.
      - **Topic**: Set the target topic to `client_disconnected`.
      - **Payload**, **QoS**, and **Retain**: Use default values.
5.  Click **Confirm** to complete the configuration.

#### Test Rule and Action

It is recommended to use [MQTTX](https://mqttx.app/) to simulate client connections and message reporting, although any MQTT client can be used.

1.  Use MQTTX to create two connections to the deployment, with ClientIDs set to `conn` and `sub`.
2.  Use client `sub` to subscribe to the republished topic `client_disconnected`.
3.  Disconnect the client `conn`. The client `sub` should receive an event message in the following format:

```json
{ 
    "clientid": "conn", 
    "username": "u_emqx", 
    "reason": "normal", 
    "disconnected_at": 1645003578536
}
```

### Forward Event Topic Messages to HTTP Services

This section demonstrates how to forward client connection and disconnection event topic messages to an HTTP service. Before you start, you need either a [VPC peering connection](../deployments/vpc_peering.md) to access the target connector via its internal IP or a [NAT gateway](../vas/nat-gateway.md) to access it via a public IP.

#### Create HTTP Server Connector

1. In the deployment menu, select **Data Integration**, and under the **Web Service** category, choose **Webhook**. If you have existing connectors, click **New Connector**, then select **Webhook** under the **Web Service** category.

2. In the **Create Connector** page, fill in the Base URL; other settings can be adjusted as needed.

   The URL should point to the HTTP service that will receive the forwarded event messages. The connector will send POST requests to this URL using the payload defined in the rule.

3. Click **Test** to verify that EMQX can successfully reach the specified URL.

4. Click **New** to complete the connector creation.

#### Create Rule and Action

1.  Click **New Rule** to enter the rule creation page.
2.  Define the Rule SQL in the **SQL Editor**. To track client disconnection events, you can use the following SQL example:
```sql
SELECT
    clientid, 
    username, 
    reason, 
    disconnected_at
FROM 
    "$events/client_disconnected"
```

3.  Click **Next** to start creating the action.
4.  From the **Connector** dropdown, select the HTTP Server connector created earlier. Leave the remaining settings as default.
5.  Click the **Confirm** button to complete the rule creation.

::: tip

For the full process and configuration of forwarding data to an HTTP service, refer to the official documentation: [Ingest MQTT Data into HTTP Server](../data_integration/http_server.md).

:::

#### Test Rule and Action

It is recommended to use [MQTTX](https://mqttx.app/) to simulate client connections and message reporting, although any MQTT client can be used.

1.  Use MQTTX to connect to the deployment, setting the ClientID to `conn`.
2.  Disconnect the client `conn`. The HTTP service should receive a POST request, with the request body in the following format:
```json
{ 
    "clientid": "conn", 
    "username": "u_emqx", 
    "reason": "normal", 
    "disconnected_at": 1645003578536
}
```