Clustering Vert.x Event Bus with Hazelcast: A Practical Decision Guide
Learn how to turn the Vert.x event bus into a distributed bus using Hazelcast, see a concrete two‑node example, and weigh the trade‑offs before you add clustering to your reactive app.
11 Sept 2026, 05:00 UTC

Problem: Local Event Bus Limits Distributed Vert.x Apps
When you run a Vert.x application inside a single JVM, the event bus is an in‑VM queue that only the local verticles can see. In a micro‑service architecture that spans several containers or hosts, you need the bus to cross process boundaries. The obvious question is: should I add a cluster manager, and if so, which one?
Thesis: Hazelcast is a Drop‑in Cluster Manager for Vert.x 3/4
Vert.x ships a ClusterManager interface that abstracts node discovery, failure detection, and message routing. Hazelcast implements this interface and provides a mature, JVM‑native cluster that handles serialization, partitioning, and rebalancing automatically. Switching to Hazelcast is a matter of adding a dependency, wiring the manager into VertxOptions, and starting the Vert.x instance in clustered mode.
1. Add Hazelcast to Your Project
Include the Vert.x‑Hazelcast artifact in your build. For Maven:
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-hazelcast</artifactId>
<version>4.4.0</version>
</dependency>
For Gradle:
implementation 'io.vertx:vertx-hazelcast:4.4.0'
Hazelcast requires Java 8+ and listens on port 5701 by default. Ensure that the port is open between all nodes.
2. Wire the Cluster Manager
Configure Vert.x to use the Hazelcast manager and start the instance in clustered mode:
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.spi.cluster.ClusterManager;
import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager;
ClusterManager mgr = new HazelcastClusterManager();
VertxOptions opts = new VertxOptions().setClusterManager(mgr);
Vertx.clusteredVertx(opts, res -> {
if (res.succeeded()) {
Vertx vertx = res.result();
// deploy verticles here
} else {
System.err.println("Cluster start failed: " + res.cause());
}
});
Running this code in two separate JVM processes will automatically discover each other via Hazelcast’s multicast or TCP discovery.
3. A Concrete Two‑Node Demo
Below is a minimal example that demonstrates cross‑node publish/subscribe. The consumer registers on address demo.addr and prints any message it receives. The producer sends a timestamped string every second. Run each verticle in its own JVM with the same Hazelcast configuration.
- Consumer (Consumer.java)
import io.vertx.core.AbstractVerticle;
public class Consumer extends AbstractVerticle {
@Override
public void start() {
vertx.eventBus().consumer("demo.addr", msg -> {
System.out.println("[Consumer] Received: " + msg.body());
});
}
}
- Producer (Producer.java)
import io.vertx.core.AbstractVerticle;
public class Producer extends AbstractVerticle {
@Override
public void start() {
vertx.setPeriodic(1000, id -> {
String msg = "Ping at " + System.currentTimeMillis();
vertx.eventBus().publish("demo.addr", msg);
System.out.println("[Producer] Sent: " + msg);
});
}
}
Execution steps:
- Start
Consumerin JVM A. - Start
Producerin JVM B. - Observe that the consumer prints messages originating from the producer.
- Stop JVM B; the consumer continues to run, and any new producer started on another node will still publish to the consumer.
Verify cluster membership by checking Hazelcast logs (e.g., INFO: Node is joined to cluster) or by querying the cluster view through the Hazelcast Management Center.
4. Trade‑Offs & Limitations
- Serialization: All objects sent on the bus must be serializable by Hazelcast. The default uses Java serialization, which can be slow. Consider configuring
Kryoor JSON codecs if performance is critical. - Split‑Brain: In a network partition, Hazelcast may split the cluster into two logical groups. Configure a split‑brain protection policy (e.g.,
Majority) to avoid inconsistent data. - Memory & Startup: Hazelcast adds heap usage (≈10 MB per member) and a startup delay of ~1–2 s for cluster formation. For single‑node, latency‑sensitive services, the local event bus is still preferable.
- Message Guarantees: The bus delivers at‑least‑once by default. If you need exactly‑once semantics, you must implement idempotent consumers or use a dedicated messaging system.
5. Actionable Takeaway
When your Vert.x application must span multiple JVMs or containers, adding Hazelcast as the cluster manager is the simplest path to a fully distributed event bus. It requires only a dependency, a small configuration change, and a clustered start. Before deploying, validate:
- All message types are serializable.
- Network ports (5701 by default) are reachable.
- Split‑brain policy matches your consistency needs.
- Memory footprint is acceptable for your deployment.
With these checks in place, you can confidently use Vert.x’s publish/subscribe and point‑to‑point APIs across a Hazelcast cluster, unlocking true reactive distributed processing.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.