Kafka event plugin

Subscribe to TRON on-chain events via the Kafka plugin — durable streams with replay support, suitable for indexers, multi-consumer pipelines, and any workflow that needs to recover from downtime.

📘

Prerequisites

The Kafka plugin pushes TRON on-chain events into Apache Kafka topics. Compared to the built-in ZeroMQ publisher, Kafka adds durability (events are retained according to the topic's retention policy, independently of consumer acknowledgements), replay (a consumer can rewind to an earlier offset), and fan-out (multiple independent consumers can read the same stream at different speeds). Use Kafka when you have indexers, analytics pipelines, or back-ends that need to recover from downtime or restart from a known checkpoint.

This page walks through building the plugin, running a Kafka broker, configuring the Fullnode, and verifying the end-to-end flow.

Recommended hardware (Fullnode and plugin host)

The Kafka plugin runs inside the Fullnode process, so its CPU and memory usage is part of the Fullnode's total workload. The Kafka broker can run on the same host or a different one — for production, prefer a separate host so broker GC or disk pressure does not affect the consensus path.

ResourceSuggested
CPU / RAM16 cores / 32 GB
SSDAt least 3 TB for Fullnode data; size Kafka separately for event volume, retention, and replication
OSLinux or macOS

1. Build the Kafka event plugin

git clone https://github.com/tronprotocol/event-plugin.git
cd event-plugin
./gradlew build

After a successful build, the current version produces event-plugin/build/plugins/plugin-kafka-3.0.0.zip. The filename may change when the plugin version changes. Use the filename actually generated under build/plugins, and use that same filename in the configuration below.

2. Deploy a Kafka broker

📘

Kafka version used in this example

The commands below demonstrate a single-node KRaft deployment with Kafka 4.3.1. The broker requires Java 17 or later; this requirement applies only to the Kafka process. For java-tron's JDK requirements, see Deploy a node.

# This example uses Kafka 4.3.1
KAFKA_SCALA=2.13
KAFKA_VERSION=4.3.1
KAFKA_BASE_URL=https://downloads.apache.org/kafka/${KAFKA_VERSION}

cd /usr/local
wget "${KAFKA_BASE_URL}/kafka_${KAFKA_SCALA}-${KAFKA_VERSION}.tgz"
wget "${KAFKA_BASE_URL}/kafka_${KAFKA_SCALA}-${KAFKA_VERSION}.tgz.sha512"
⚠️

Verify the download

Before extracting the archive, obtain the matching .sha512 or .asc file from the same Apache Kafka download directory, then verify its SHA-512 checksum or OpenPGP signature using the Apache download verification guide. Do not extract or run a binary that fails verification.

After verification succeeds, extract the archive and enter the Kafka directory:

tar -xzf "kafka_${KAFKA_SCALA}-${KAFKA_VERSION}.tgz"
cd "kafka_${KAFKA_SCALA}-${KAFKA_VERSION}"

Initialize the KRaft storage directory and start the Kafka broker. The following single-node commands are intended only for development and testing:

# Generate a cluster ID and format the storage directory
KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"
bin/kafka-storage.sh format --standalone -t "$KAFKA_CLUSTER_ID" -c config/server.properties

# Start the Kafka broker
bin/kafka-server-start.sh config/server.properties &

For production, deploy a multi-broker KRaft cluster, manage the Kafka processes with a process manager, and configure topic replication and retention to match your availability and storage requirements.

3. Configure the Fullnode

Add an event.subscribe block to config.conf:

event.subscribe = {
  enable = true         // enable event subscription
  version = 1            // 1 = V2.0 event framework, 0 = V1.0 (default)
  startSyncBlockNum = 0  // V2.0 only — see below

  native = {
    useNativeQueue = false   // false routes events through the external plugin
    bindport = 5555
    sendqueuelength = 1000
  }

  path = "/path/to/plugin-kafka-3.0.0.zip"   // absolute path to the plugin package
  server = "127.0.0.1:9092"                  // Kafka broker address
  dbconfig = ""                              // MongoDB-only — leave empty for Kafka
  contractParse = true
}
FieldMeaning
enableSet to true to enable event subscription.
versionEvent framework version. 1 = V2.0 (supports historical backfill). 0 = V1.0 (default). See Event service framework for the differences.
startSyncBlockNumV2.0 only. 0 or negative disables historical sync; a positive value replays events starting from that block height. Use the latest plugin version when enabling.
native.useNativeQueueMust be false to route through the Kafka plugin. (true selects the built-in ZeroMQ publisher.)
pathAbsolute path to plugin-kafka-3.0.0.zip.
serverKafka broker address as IP:port. Default Kafka port is 9092. When the broker and Fullnode run on different hosts, use a broker address reachable from the Fullnode and configure Kafka's listeners and advertised.listeners accordingly.
dbconfigUsed only by the MongoDB plugin; leave empty for Kafka.
contractParseWhen true, contract events are decoded against the contract's ABI before being published.

Choose the event types

The Fullnode supports seven trigger types — block, transaction, contractevent, contractlog, and their solidified counterparts. For the full list with payload fields and use-case guidance, see Event types. Pick the smallest set that meets your application's needs — subscribing to many types simultaneously increases the Fullnode's CPU and memory cost.

Add one topics entry per category you want to publish. The topic field is the Kafka topic name the consumer will subscribe to (must match a topic you create in Kafka in step 4):

topics = [
  {
    triggerName = "block"   // built-in identifier — must not be changed
    enable = true           // false leaves the entry inactive
    topic = "block"         // Kafka topic name; can be customized
  }
]

Configure filters (optional)

Use the filter block to narrow the stream by block range, contract address, or contract topic:

filter = {
  fromblock = ""        // "", "earliest", or a block number
  toblock = ""          // "", "latest", or a block number
  contractAddress = [
    ""                  // contract address; empty matches all contracts
  ]
  contractTopic = [
    ""                  // event topic hash; empty matches all topics
  ]
}

Filters apply to contract events / logs only. Block, transaction, and solidified-block streams are not filtered.

4. Create the Kafka topics

Before starting the Fullnode, pre-create a matching Kafka topic for each enabled event type in your topics configuration:

bin/kafka-topics.sh --create --topic block --bootstrap-server localhost:9092

This prevents event delivery from depending on the broker's automatic topic creation setting. Repeat for each subscribed event category.

5. Start the Fullnode with event subscription enabled

Event subscription is disabled by default. Set event.subscribe.enable = true in config.conf, then start the Fullnode:

java -jar FullNode.jar -c config.conf

Verify the plugin loaded successfully:

grep -i eventplugin logs/tron.log

A successful load logs:

[o.t.c.l.EventPluginLoader] '/path/to/plugin-kafka-3.0.0.zip' loaded

If the plugin fails to load, the log entry will include the failure reason — typically a missing plugin package, an unreachable Kafka broker, or a misconfigured path.

6. Consume events

Use the standard Kafka console consumer (or any Kafka client library) to read from the topic:

bin/kafka-console-consumer.sh --topic block --from-beginning --bootstrap-server localhost:9092

Each event is a JSON message:

{
  "timeStamp": 1539973125000,
  "triggerName": "blockTrigger",
  "blockNumber": 3341315,
  "blockHash": "000000000032fc03440362c3d42eb05e79e8a1aef77fe31c7879d23a750f2a31",
  "transactionSize": 16,
  "latestSolidifiedBlockNumber": 3341297,
  "transactionList": [
    "8757f846e541b51b5692a2370327f4b8031125f4557f8ad4b1037d4452616d39",
    "f6adab7814b34e5e756170f93a31a0c3393c5d99eff11e30271916375adc7467",
    "89bcbcd063a48ef4a5678a033acf5edbb6b17419a3c91eb0479a3c8598774b43"
  ]
}

From this point any Kafka consumer — kafka-console-consumer.sh, a kafkacat-based pipeline, or your application using librdkafka, confluent-kafka-python, sarama, etc. — can subscribe and process the stream.


Related resources