Skip to content
Stand with Ukraine flag

Message Queue

All ThingsBoard services communicate through a message queue. Every message is partitioned by entity ID, so all messages for a given device always land on the same partition — preserving order and enabling stateful processing in the Actor System.

ThingsBoard supports two queue implementations. Set the backend with the TB_QUEUE_TYPE environment variable:

BackendTB_QUEUE_TYPEPersistenceUse case
In-Memoryin-memoryNone — messages lost on restartDevelopment, single-node demos
Apache KafkakafkaDisk-based, survives restartsProduction, any cluster deployment

The message queue described on this page is the infrastructure-level transport — Kafka or in-memory — that carries messages between ThingsBoard services (transports, core, rule engine, JS executors).

This is different from Rule Engine Queues, which are a higher-level abstraction configured in the ThingsBoard UI. Rule Engine Queues control how messages are submitted to and processed by rule chains — submit strategy (burst, batch, sequential), retry policy, polling interval, and parallelism. They run on top of the message queue backend: when you configure a Rule Engine Queue named “HighPriority”, its messages still flow through Kafka (or in-memory) under the hood.

The diagram below shows how the main services communicate through Kafka topics:

When running with Kafka, ThingsBoard creates the following topics. Each topic has a specific role in the data pipeline:

TopicDirectionPurpose
tb_rule_engineTransport → Rule EngineTelemetry, attributes, RPC requests, device lifecycle events
tb_coreRule Engine → CoreEntity lifecycle events, connectivity updates, subscription management
tb_core.notificationsAny → CoreLightweight notifications (WebSocket pushes, entity invalidations)
tb_transport.api.requestsTransport → CoreCredential validation, attribute fetch, claim requests
tb_transport.api.responsesCore → TransportAuthentication results, attribute values
TopicDirectionPurpose
js.eval.requestsTB Node → JS ExecutorJavaScript evaluation requests from rule engine script nodes
js.eval.responsesJS Executor → TB NodeScript evaluation results
TopicDirectionPurpose
tb_ota_packageCore → TransportOTA firmware/software update distribution
tb_housekeeperInternalCleanup tasks — orphaned entities, expired sessions, stale data
tb_housekeeper.reprocessingInternalFailed housekeeper tasks queued for retry (90-day retention)
TopicDirectionPurpose
tb_edgeCore ↔ EdgeEdge synchronization commands and responses
tb_edge.notificationsCore → EdgeEdge event notifications
TopicDirectionPurpose
tb_cf_eventCore → CF EngineCalculated field trigger events
tb_cf_stateCF EngineCalculated field state snapshots (compacted topic, infinite retention)
TopicDirectionPurpose
edqs.eventsCore → EDQSEntity change events for query indexing
edqs.requestsAPI → EDQSQuery requests (3-minute retention)
edqs.stateEDQSIndex state snapshots (compacted topic, infinite retention)

Messages are assigned to Kafka partitions using a hash of the entity ID. ThingsBoard supports three hash functions, configured via TB_QUEUE_PARTITIONS_HASH_FUNCTION_NAME:

Hash FunctionValueNotes
MurmurHash3 128-bitmurmur3_128Default — good distribution, fast
MurmurHash3 32-bitmurmur3_32Lighter, slightly less uniform
SHA-256sha256Cryptographic, slower but uniform

Because the same entity always maps to the same partition, a single consumer thread processes all messages for that entity in order. This is critical for correctness — device state updates, rule chain processing, and attribute writes must happen sequentially.

Partition count controls parallelism. More partitions allow more consumer threads, increasing throughput. The number of partitions per topic is configured via topic property strings (e.g., TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES includes partitions:1 by default for the rule engine topic).

These environment variables control how ThingsBoard produces messages to Kafka:

VariableDefaultDescription
TB_KAFKA_ACKSallAcknowledgment level. all = wait for all in-sync replicas (safest). 1 = leader only (faster). 0 = fire-and-forget (not recommended).
TB_KAFKA_BATCH_SIZE16384Maximum batch size in bytes before sending to broker
TB_KAFKA_LINGER_MS1Milliseconds to wait for more records before sending a batch. Higher values increase throughput at the cost of latency.
TB_KAFKA_COMPRESSION_TYPEnoneCompression algorithm: none, gzip. Use gzip to reduce network bandwidth in high-throughput deployments.
TB_KAFKA_RETRIES1Retry count for transient send failures
TB_KAFKA_MAX_REQUEST_SIZE1048576Maximum request size in bytes (1 MB default)

These variables control how ThingsBoard consumes messages from Kafka:

VariableDefaultDescription
TB_QUEUE_KAFKA_MAX_POLL_RECORDS8192Maximum records returned per poll() call. Lower values reduce processing latency; higher values increase throughput.
TB_QUEUE_KAFKA_MAX_POLL_INTERVAL_MS300000Maximum time between poll() calls before the consumer is considered dead and rebalanced (5 minutes).
TB_QUEUE_KAFKA_SESSION_TIMEOUT_MS10000Heartbeat session timeout. If Kafka doesn’t receive a heartbeat within this window, the consumer is evicted.
TB_QUEUE_KAFKA_AUTO_OFFSET_RESETearliestWhere to start reading when no committed offset exists: earliest (beginning) or latest (end).
TB_QUEUE_KAFKA_MAX_PARTITION_FETCH_BYTES16777216Maximum data per partition per fetch request (16 MB)
TB_QUEUE_KAFKA_FETCH_MAX_BYTES134217728Maximum total data per fetch request across all partitions (128 MB)

Most topics use time-based retention (default 7 days / 604800000 ms). Notable exceptions:

TopicRetentionCleanup PolicyReason
JS Executor (js.eval.*)1 dayDeleteShort-lived request/response pairs
Housekeeper reprocessing90 daysDeleteFailed tasks need longer retry window
CF State (tb_cf_state)InfiniteCompactState snapshots — only latest value per key matters
EDQS State (edqs.state)InfiniteCompactIndex state — compacted to latest per key
EDQS Requests (edqs.requests)3 minutesDeleteEphemeral query requests

Topic properties (retention, segment size, partition count, min.insync.replicas) are configurable per topic via environment variables like TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES. The format is semicolon-separated key:value pairs:

retention.ms:604800000;segment.bytes:52428800;retention.bytes:1048576000;partitions:1;min.insync.replicas:1

Set TB_QUEUE_KAFKA_REPLICATION_FACTOR (default 1) to control how many Kafka brokers hold a copy of each partition. For production clusters, set this to 3 with at least 3 Kafka brokers.

ThingsBoard can log consumer group lag — the difference between the latest message offset and the consumer’s committed offset. Enable with TB_QUEUE_KAFKA_CONSUMER_STATS_ENABLED (default true). Lag statistics print every TB_QUEUE_KAFKA_CONSUMER_STATS_MIN_PRINT_INTERVAL_MS (default 60 seconds).

High consumer lag indicates the service cannot keep up with incoming message volume — scale the service or increase partition count.

For the complete list of queue and Kafka environment variables, see Configuration Reference.