Built-in actions and message republishing
Once the rule SQL has worked out a result, the action decides where that result goes. This chapter goes deep on the two built-in actions Republish and Console Output, and looks at how a config file declares an action.
Why this matters
Chapter 9 taught you to write rule SQL, but the real value of the Rule Engine is that something actually happens once a rule matches. Data that stops at the SQL output is data you cannot use. An action turns the result the rule produced into real behavior: republishing it to another topic, printing it to the log for debugging, or sending it into an external data system.
This chapter focuses on the built-in actions of EMQX 5.8.9, above all republish and console. Actions that send data out to an external system (Webhook, Kafka, a database) rely on Connectors and Sinks, which Chapter 11 covers in detail.
Core concepts
In a rule's actions you can configure one or more actions, and the rule runs them in order. The data an action uses comes from the SQL result: with placeholder syntax such as ${field} you push a field of the rule output into an action parameter (putting the payload or clientid the SQL selected into the republish topic or payload, for example).
The three built-in actions in EMQX 5.8.9:
- Message Republishing: publishes the rule result to an MQTT topic.
- Console Output: prints the result to the console or the log, mainly for debugging.
- Forwarding to Sinks: hands the result to a Sink (Chapter 11).
When you create a rule, pick the action from the "Add Action" dropdown; you can also declare the same rule and action in the emqx.conf config file.
Terms at a glance
| Term | Plain English | In one line |
|---|---|---|
| Action | what the rule does next | The output behavior that runs once a rule matches |
| Republish | publish it again elsewhere | Publishes the rule result to another MQTT topic |
| Console Output | print it to the console | Prints the result to the console or the log, for debugging |
| Forwarding | send it on | Sends the result into a Sink (an external system) |
${key} | placeholder | References a field of the rule output inside an action parameter |
Hands-on
Create a rule
In the Dashboard go to Integration → Rules → Create, give the rule a name, and type
SELECT * FROM "t/#"into the SQL box.Add a Republish action
Click Add Action on the right and pick Republish from the Action dropdown; set Target Topic to
a/1, QoS to0and Retain tofalse.Set the Payload placeholder
Type
${payload}into the Payload field so the republished message keeps the original payload; when you need to, build a custom payload out of fields such as${clientid}.Handle MQTT 5.0 properties (optional)
Turn on the "MQTT 5.0 Message Properties" switch to set Payload Format Indicator, Message Expiry Interval, Content Type, Response Topic, Correlation Data and other properties.
Create it and verify
Click Create to finish. Subscribe to
a/1, publish a message tot/1, and the republished result should arrive; you can also simulate it directly with Test the Rule.
Republish and Console Output
Republish is the everyday "reshape the data and reroute it" action. In the official example, messages matching t/# are republished to a/1. The source example takes t/#a/1: republishing does not intercept the original message, so a client subscribed to t/1 still receives it as usual and simply gets one extra copy on a/1. Adding the Direct Dispatch switch delivers the message straight to subscribers, which keeps it from triggering other rules and falling into recursion.
The common Republish parameters:
| Parameter | What it means |
|---|---|
| Topic | The republish target topic; use ${…} to build a dynamic topic |
| QoS | The QoS level of the republished message |
| Retain | Whether to publish it as a retained message |
| Payload | The republished payload template (commonly ${payload}) |
| MQTT 5.0 properties | Optional: Payload Format, Expiry, Content Type, Response Topic, Correlation Data |
| Direct Dispatch | Delivers straight to subscribers and avoids rule recursion |
The Console Output action only prints the rule result to the console or the log (in the form [rule action] ruleID + Action Data + Envs). Use it for debugging only: when EMQX starts in the foreground (the Docker default) the output goes to the console; when it starts under systemd it goes to the journal, which you read with journalctl. The official docs warn plainly that using console in production can slow things down.
Declaring actions and ${var} in a config file
Rules and actions can also go into emqx.conf, where they take effect before EMQX starts. Define them under the rule_engine namespace with rules.<id>, like this:
rule_engine {
rules.my_republish_rule {
sql = "SELECT qos, payload.x as y FROM \"t/a\""
actions = [
{
function = republish
args = {
topic = "t/b"
qos = "${qos}"
payload = "y: ${y}"
}
}
]
}
}
Here ${qos} and ${y} are placeholders that reference fields of the SQL output. For example, when t/a receives a {"x":1}, the rule first picks out qos and renames the payload's x to y, then republishes to t/b with the payload y: 1.
To name an external integration Sink as a rule's action, put the bridge ID straight into the actions array (such as "mqtt:my_egress_mqtt_bridge"); for a console action, such as actions = [{function = console}], the rule output is printed to the console. Event rules (a client coming online, $events/client_connected, for instance) can be declared in a config file just the same.
Troubleshooting
- No republished message arrives: check that the rule is enabled, that the SQL's FROM pattern matches the topic you publish to, that the action was saved, and that the target topic and QoS are right; simulate it first with "Test the Rule".
- Nothing shows up in the console: when EMQX starts in the background the output goes to the journal, which you read with
journalctl; when it runs in the Docker foreground, look at the console. - The payload is not in the format you expected: the republish payload is a string template, so you have to type out the shape you want (for example
${payload}, or text mixed with${field}). - The rule triggers itself and recurses: if the Republish target topic also matches the same rule's
FROM, it fires again without end. Avoid that with Direct Dispatch, or change the target topic.
FAQ
Does Republish block the original message?
No. Republish only sends one extra copy to the target topic; a message published to t/1 still reaches the clients subscribed to t/1 as usual.
Is Console Output suitable for production?
No. The official docs mark it as a debugging tool, and heavy output slows things down; in production use republish or send the data to a Sink.
Can I configure several actions at once?
Yes. A rule's actions is an array, so you can add one action after another in the UI and list them as an array in the config file; the rule runs them in order.
When do I use republish, and when do I use a Sink?
If you are only moving the data to a different topic, use republish; to send it to an external system (a database, HTTP, Kafka, a remote MQTT broker), use Forwarding to Sinks.