- Key characteristics
- Typical use cases
- Rule Engine message
- Rule node
- Rule node connection
- Rule chain
- Message processing result
- Predefined message types
- Rule node types
- Configuration
- Rule Engine statistics
- Debugging
- Managing rule chains
- Architecture
- Custom REST API calls to Rule Engine
- Tutorials
- Troubleshooting
Rule Engine in ThingsBoard is the core data processing mechanism responsible for receiving, transforming, routing, and reacting to events and telemetry coming from devices and related assets.
Rule Engine built around three main components:
- Message - any incoming event. It can be an incoming data from devices, device life-cycle event, REST API event, RPC request, etc.
- Rule node - a function that is executed on an incoming message. There are many different Node types that can filter, transform or execute some action on incoming Message.
- Rule chain - nodes are connected with each other with relations, so the outbound message from rule node is sent to next connected rule nodes.
Key characteristics
- Stream processing. Incoming data (telemetry, attributes, RPC, events) is immediately processed by the Rule Engine, where it can be filtered, enriched, or transformed.
- Rule chain as a workflow. Data processing is organized into Rule chains — workflows composed of individual Rule nodes. Each node performs a specific action such as filtering, saving data to a database, sending a notification, or calling an external API.
- Flexibility and Extensibility. The Rule Engine supports both built-in nodes and custom logic via scripts (JavaScript or TBEL). It also allows integrations with external systems (HTTP, Kafka, MQTT).
- Integrations and Reactivity. The Rule Engine can trigger business logic in response to events — for example, sending an email or SMS when a temperature threshold is exceeded, or integrating with external services and platforms.
Typical use cases
Here are some common scenarios that can be configured using ThingsBoard Rule Chains:
- Data validation and transformation – Validate and modify incoming telemetry or attributes before persisting them in the database.
- Telemetry aggregation – Copy telemetry or attributes from devices to related assets to enable aggregation. For example, data from multiple devices can be combined into a related Asset for summary analytics.
- Alarm management – Create, update, or clear alarms based on defined conditions.
- Device life-cycle monitoring – Trigger actions when device state changes. For example, generate alerts when a device goes online or offline.
- Data enrichment – Load additional context required for processing. For example, load temperature threshold value for a device that is defined in device's Customer or Tenant attribute.
- External system integration – Trigger REST API calls to external applications and services.
- Notifications – Send email alerts when complex events occur, with the ability to include attributes from related entities in the email template.
- User personalization – Take into account user preferences during event processing.
- Remote control – Execute RPC calls to devices based on defined conditions.
- Big data / cloud integration – Connect to external pipelines and platforms such as Kafka, Spark, or AWS services.
Rule Engine message
Rule Engine Message is a serializable, immutable data structure that represent various messages in the system. For example:
- Incoming telemetry, attribute update or RPC call from device;
- Entity life-cycle event: created, updated, deleted, assigned, unassigned, attributes updated;
- Device status event: connected, disconnected, active, inactive, etc;
- Other system events.
Rule Engine Message contains the following information:
- Message ID: time based, universally unique identifier;
- Originator of the message: Device, Asset or other Entity identifier;
- Type of the message: “Post telemetry” or “Inactivity Event”, etc;
- Payload of the message: JSON body with actual message payload;
- Metadata: List of key-value pairs with additional data about the message.
Rule node
Rule Node is a basic component of Rule Engine that process single incoming message at a time and produce one or more outgoing messages. Rule Node is a main logical unit of the Rule Engine. Rule Node can filter, enrich, transform incoming messages, perform action or communicate with external systems.
Rule node connection
Rule Nodes may be connected to other rule nodes. Each relation has relation type, a label used to identify logical meaning of the relation. When rule node produces the outgoing message it always specifies the relation type which is used to route message to next nodes.
Typical rule node relations are “Success” and “Failure”. Rule nodes that represent logical operations may use “True” or “False”. Some specific rule nodes may use completely different relation types, for example: “Post Telemetry”, “Attributes Updated”, “Entity Created”, etc.
Some rule nodes support custom connection names. Just type your custom connection name and click the “Create a new one!” link:
All connection names are case-sensitive.
Rule chain
Rule Chain is a logical group of rule nodes and their relations. For example, the rule chain below will:
- save all telemetry messages to the database;
- raise “High Temperature Alarm” if temperature field in the message will be higher then 50 degrees;
- raise “Low Temperature Alarm” if temperature field in the message will be lower then -40 degrees;
- log failure to execute the temperature check scripts to console in case of logical or syntax error in the script.
Tenant administrator is able to define one Root Rule Chain and optionally multiple other rule chains. Root rule chain handles all incoming messages and may forward them to other rule chains for additional processing. Other rule chains may also forward messages to different rule chains.
For example, the rule chain below will:
- raise “High Temperature Alarm” if temperature field in the message will be higher then 50 degrees;
- clear “High Temperature Alarm” if temperature field in the message will be less then 50 degrees;
- forward events about “Created” and “Cleared” alarms to external rule chain that handles notifications to corresponding users.
Message processing result
There are three possible results of message processing: Success, Failure and Timeout. The message processing attempt is marked as “Success” when the last rule node in the processing chain successfully process the message. The message processing attempt is marked as “Failure” if one of the rule nodes produce “Failure” of message processing, and there is no rule nodes to handle that failure. The message processing attempt is marked as “Timeout” when overall time of processing exceed configurable threshold.
See diagram below and let’s review the possible scenarios:
If the “Transformation” script fails, the message is not marked as “Failed”, because there is a “Save to DB” node connected with “Failure” relation. If the “Transformation” script is successful, it will be pushed to “External System” with the REST API call. If the external system is overloaded, the REST API call may “hang” for some time. Let’s assume the overall timeout for message pack processing is 20 seconds. Let’s ignore Transformation script execution time because it is < 1ms. So, if the “External System” will reply within 20 seconds, the message will be successfully processed. Similar, if “Save to DB” call will succeed, the message will be successfully processed. However, if the external system will not reply within 20 seconds, the message processing attempt will be marked as “timed-out”. Similar, if “Save to DB” call will fail, the message will be marked as failed.
Rule Engine queue
See new documentation
Queue submit strategy
See new documentation
Queue processing strategy
See new documentation
Default queues
See new documentation
Predefined message types
List of the predefined Message Types is presented in the following table:
Message Type | Display Name | Description | Message metadata | Message payload |
POST_ATTRIBUTES_REQUEST | Post attributes | Request from device to publish client side attributes (see attributes api for reference) | deviceName - originator device name, deviceType - originator device type |
key/value json: { |
POST_TELEMETRY_REQUEST | Post telemetry | Request from device to publish telemetry (see telemetry upload api for reference) | deviceName - originator device name, deviceType - originator device type, ts - timestamp (milliseconds) |
key/value json: { |
TO_SERVER_RPC_REQUEST | RPC Request from Device | RPC request from device (see client side rpc for reference) | deviceName - originator device name, deviceType - originator device type, requestId - RPC request Id provided by client |
json containing method and params: { |
RPC_CALL_FROM_SERVER_TO_DEVICE | RPC Request to Device | RPC request from server to device (see server side rpc api for reference) | requestUUID - internal request id used by sustem to identify reply target, expirationTime - time when request will be expired, oneway - specifies request type: true - without response, false - with response |
json containing method and params: { |
ACTIVITY_EVENT | Activity Event | Event indicating that device becomes active | deviceName - originator device name, deviceType - originator device type |
json containing device activity information: { |
INACTIVITY_EVENT | Inactivity Event | Event indicating that device becomes inactive | deviceName - originator device name, deviceType - originator device type |
json containing device activity information, see Activity Event payload |
CONNECT_EVENT | Connect Event | Event produced when device is connected | deviceName - originator device name, deviceType - originator device type |
json containing device activity information, see Activity Event payload |
DISCONNECT_EVENT | Disconnect Event | Event produced when device is disconnected | deviceName - originator device name, deviceType - originator device type |
json containing device activity information, see Activity Event payload |
ENTITY_CREATED | Entity Created | Event produced when new entity was created in system | userName - name of the user who created the entity, userId - the user Id |
json containing created entity details: { |
ENTITY_UPDATED | Entity Updated | Event produced when existing entity was updated | userName - name of the user who updated the entity, userId - the user Id |
json containing updated entity details, see Entity Created payload |
ENTITY_DELETED | Entity Deleted | Event produced when existing entity was deleted | userName - name of the user who deleted the entity, userId - the user Id |
json containing deleted entity details, see Entity Created payload |
ENTITY_ASSIGNED | Entity Assigned | Event produced when existing entity was assigned to customer | userName - name of the user who performed assignment operation, userId - the user Id, assignedCustomerName - assigned customer name, assignedCustomerId - Id of assigned customer |
json containing assigned entity details, see Entity Created payload |
ENTITY_UNASSIGNED | Entity Unassigned | Event produced when existing entity was unassigned from customer | userName - name of the user who performed unassignment operation, userId - the user Id, unassignedCustomerName - unassigned customer name, unassignedCustomerId - Id of unassigned customer |
json containing unassigned entity details, see Entity Created payload |
ADDED_TO_ENTITY_GROUP | Added to Group | Event produced when entity was added to Entity Group. This Message Type is specific to ThingsBoard PE. | userName - name of the user who performed assignment operation, userId - the user Id, addedToEntityGroupName - entity group name, addedToEntityGroupId - Id of entity group |
empty json payload |
REMOVED_FROM_ENTITY_GROUP | Removed from Group | Event produced when entity was removed from Entity Group. This Message Type is specific to ThingsBoard PE. | userName - name of the user who performed unassignment operation, userId - the user Id, removedFromEntityGroupName - entity group name, removedFromEntityGroupId - Id of entity group |
empty json payload |
ATTRIBUTES_UPDATED | Attributes Updated | Event produced when entity attributes update was performed | userName - name of the user who performed attributes update, userId - the user Id, scope - updated attributes scope (can be either SERVER_SCOPE or SHARED_SCOPE) |
key/value json with updated attributes: { |
ATTRIBUTES_DELETED | Attributes Deleted | Event produced when some of entity attributes were deleted | userName - name of the user who deleted attributes, userId - the user Id, scope - deleted attributes scope (can be either SERVER_SCOPE or SHARED_SCOPE) |
json with attributes field containing list of deleted attributes keys: { |
ALARM | Alarm event | Event produced when an alarm was created, updated or deleted |
All fields from original Message Metadata
isNewAlarm - true if a new alram was just created isExistingAlarm - true if an alarm is existing already isClearedAlarm - true if an alarm was cleared |
json containing created alarm details:
{
|
ALARM_ASSIGNED | Alarm Assigned | Event produced when an alarm was assigned to some user |
All fields from original Message Metadata
entityName - name of alarm entityType - ALARM userEmail - user email userFirstName - user first name userId - user id userLastName - user last name userName - user name |
json containing alarm details, see Alarm event |
ALARM_UNASSIGNED | Alarm Unassigned | Event produced when an alarm was unassigned from user |
All fields from original Message Metadata
entityName - name of alarm entityType - ALARM userEmail - user email userFirstName - user first name userId - user id userLastName - user last name userName - user name |
json containing alarm details, see Alarm event |
COMMENT_CREATED | Comment Created | Event produced when an alarm comment was created |
All fields from original Message Metadata
userId - user id userName - user name userFirstName - first name of user userLastName - last name of user userEmail - email of user comment - json object containing comment details and text of comment |
json containing alarm details, see Alarm event |
COMMENT_UPDATED | Comment Updated | Event produced when an alarm comment was updated |
All fields from original Message Metadata
userId - user id userName - user name userFirstName - first name of user userLastName - last name of user userEmail - email of user comment - json object containing comment details and text of comment |
json containing alarm details, see Alarm event |
REST_API_REQUEST | REST API Request to Rule Engine | Event produced when user executes REST API call | requestUUID - the unique request id, expirationTime - the expiration time of the request |
json with request payload |
Rule node types
All available rule nodes are grouped in correspondence with their nature:
- Filter Nodes are used for message filtering and routing;
- Enrichment Nodes are used to update meta-data of the incoming Message;
- Transformation Nodes are used for changing incoming Message fields like Originator, Type, Payload, Metadata;
- Action Nodes execute various actions based on incoming Message;
- External Nodes are used to interact with external systems.
Configuration
Each Rule Node may have specific configuration parameters that depend on the Rule Node Implementation. For example, “Filter - script” rule node is configurable via custom JS function that process incoming data. “External - send email” node configuration allows to specify mail server connection parameters.
Rule Node configuration window may be opened by double-clicking on the node in the Rule Chain editor:
Test script functions
Some rule nodes have specific UI feature that allow users to test TBEL/JS functions. Once you click on the Test Filter Function you will see the JS Editor that allows you to substitute input parameters and verify the output of the function.
You can define:
- Message Type in the top left field.
- Message payload in the left Message section.
- Metadata in right Metadata section.
- Actual TBEL/JS script in Filter section.
After pressing Test output will be returned in right Output section.
Rule Engine statistics
ThingsBoard Team have prepared the “default” dashboard for Rule Engine statistics. This dashboard is automatically loaded for each tenant. You may access it by navigating to “Api Usage”->”View statistics” (see screen below).
The statistics collection is enabled by default and is controlled via configuration properties.
You may notice insights about errors in processing and what causes them on the dashbaord below:
Debugging
ThingsBoard provides ability to review incoming and outgoing messages for each Rule Node. To enable debug, user need to ensure that “Debug mode” checkbox is selected in the main configuration window (see first image in the Configuration section).
Once debug is enabled, user is able to see incoming and outgoing messages info as long as corresponding relation types. See image below for a sample debug messages view:
Managing rule chains
Rule chains page displays a table of configured tenant rule chains. From here, you can create, export/import, delete, and mark the rule chain as root.
Create rule chain
To add a new rule chain, you should:
- Navigate to the "Rule chains" page. Then click on the "plus" icon in the upper right corner, and select "Create new rule chain";
- Specify a name for the rule chain. If necessary, enable "Debug mode". Click "Add";
- The new rule chain is created. To open rule chain click on it.



Import/Export
You are able to export your rule chain to а JSON file and import it to the same or another ThingsBoard instance.
Export rule chain
In order to export rule chain, you should:
- Go to the “Rule chains” page.
- Click the “Export rule chain” icon in the row of the desired rule chain.
A JSON file containing the configuration of that rule chain will be saved to your computer.

Import rule chain
To import rule chain from а JSON file, you should:
- Navigate to the "Rule chains" page and click on the "+" button in the upper right corner of the screen and select "Import rule chain" option.
- Drag and drop the JSON file with the Rule chain configuration into the dialog and click "Import".
- The imported Rule chain will open. Save it by clicking "Apply changes" in the bottom-right corner.
- The Rule chain is now successfully imported.




Make rule chain root
To make rule chain root, you should:
- Navigate to the "Rule chains" page and click on the "Make rule chain root" button located on the particular rule chain row;
- Please confirm your actions in the dialog box;
- The selected rule chain has now become the root.



Delete rule chain
You can delete a rule chain using one of the following ways:
First way:
- Click a trash icon can opposite the rule chains`s name you want to delete;
- Confirm deleting a rule chain in the dialog box.


Second way:
- Click on the "Rule chain details" button located on the particular rule chain row;
- In the rule chain details, click on the "Delete rule chain" button;
- Confirm deleting the rule chain in the dialog box.



You can also delete multiple rule chains at once.
- Mark one or multiple rule chains you want to delete. Click on the trash bin icon in the top right corner;
- Confirm deleting rule chains in the dialog box.


Architecture
To learn more about internals of the Rule Engine, see architecture page.
Custom REST API calls to Rule Engine
ThingsBoard provides API to send custom REST API calls to the Rule Engine, process the payload of the request and return result of the processing in response body. This is useful for a number of use cases. For example:
- extend existing REST API of the platform with custom API calls;
- enrich REST API call with the attributes of device/asset/customer and forward to external system for complex processing;
- provide custom API for your custom widgets.
To execute the REST API call, you may use rule-engine-controller REST APIs:
Note: the entity id you have specified in the call will be the originator of Rule Engine message. If you do not specify the entity id parameters, your user entity will become an originator of the message.
Tutorials
ThingsBoard authors have prepared several tutorials to help you get started with designing rule chains by example:
- Transform incoming messages from device
- Transform incoming messages using previous messages from device {:target=”_blank”}
- Create and clear alarms on incoming device messages
- Send emails to customer on device alarm {:target=”_blank”}
- Send messages between related devices
See more tutorials here.
Troubleshooting
If you are using Kafka queue for processing messages, ThingsBoard provides the ability to monitor if the rate of pushing messages to the Kafka is faster than rate of consuming and processing them (in such case you will have a growing latency for message processing). To enable this functionality, you need to ensure that Kafka consumer-stats are enabled (see queue.kafka.consumer-stats section of the Configuration properties)
Once Kafka consumer-stats are enabled, you will see logs (see Troubleshooting) about offset lag for consumer groups (there are consumer-group logs for tb-core, tb-rule-engine and all transport services).
Here’s an example of the log message:
1
2021-03-19 15:01:59,794 [kafka-consumer-stats-11-thread-1] INFO o.t.s.q.k.TbKafkaConsumerStatsService - [re-Main-consumer] Topic partitions with lag: [[topic=[tb_rule_engine.main.0], partition=[0], committedOffset=[5413], endOffset=[5418], lag=[5]]].
From this message we can see that there are 5 (5418 - 5413 = 5) messages pushed to the Main queue (tb_rule_engine.main.0 Kafka topic) but not yet processed.
In general the logs have the following structure:
1
TIME [STATS_PRINTING_THREAD_NAME] INFO o.t.s.q.k.TbKafkaConsumerStatsService - [CONSUMER_GROUP_NAME] Topic partitions with lag: [[topic=[KAFKA_TOPIC], partition=[KAFKA_TOPIC_PARTITION], committedOffset=[LAST_PROCESSED_MESSAGE_OFFSET], endOffset=[LAST_QUEUED_MESSAGE_OFFSET], lag=[LAG]],[topic=[ANOTHER_TOPIC], partition=[], committedOffset=[], endOffset=[], lag=[]],...].
Where:
CONSUMER_GROUP_NAME
- name of the consumer group which is processing messages (could be any of the rule-engine queues, core queue etc)KAFKA_TOPIC
- name of the exact Kafka topicKAFKA_TOPIC_PARTITION
- number of the topic’s partitionLAST_PROCESSED_MESSAGE_OFFSET
- the sequence number of the last message which was processed by the consumer (last acknowledged message in the Rule Engine etc)LAST_QUEUED_MESSAGE_OFFSET
- the sequence number of the last message that was successfully pushed to the Kafka topicLAG
- the amount of unprocessed messages
NOTE: Logs about consumer lag are printed only if there is a lag for this consumer group.