EventMesh Getting Started

This guide takes you from zero to a running EventMesh Runtime with a working publisher and subscriber, using the recommended HTTP + CloudEvents path. Configuration reference: eventmesh-configuration.md. SDK details: eventmesh-client-guide.md.

Capability maturity levels (GA / Beta / Experimental / Legacy) are defined in the capability status table in the main README.


1. Prerequisites

  • JDK 21+ (Temurin recommended)
  • Docker (for the container path), or a local install of one storage backend:
  • (SDK only) Java 11+ application with eventmesh-sdk-java on the classpath

2. Choose a storage backend

The EventMesh Runtime is stateless — it owns subscriptions, offsets and delivery, and uses the MQ purely as a write-ahead log (WAL). Pick one backend per deployment; the client side never changes.

BackendType valueNotes
RocketMQ 4.xrocketmqclassic PULL over remoting
RocketMQ 5.xrocketmq55.x POP + Lite Topic support
Kafkakafkaassign+seek+poll (no consumer groups), SASL/SSL supported

3. Run the Runtime

Option A — Docker

sudo docker pull apache/eventmesh:latest
sudo docker run -d --name eventmesh \
  -e EVENTMESH_STORAGE_TYPE=kafka \
  -e EVENTMESH_KAFKA_NAMESRV=YOUR_KAFKA:9092 \
  -p 8080:8080 -p 8081:8081 \
  apache/eventmesh:latest

Ports: 8080 = traffic HTTP (/events/*), 8081 = admin HTTP (/admin/*). The WebSocket push port (8082) and the connector runtime admin port (8083) are opt-in.

Option B — From source

git clone https://github.com/apache/eventmesh.git
cd eventmesh

# pick your backend via EVENTMESH_STORAGE_TYPE (rocketmq | rocketmq5 | kafka)
export EVENTMESH_STORAGE_TYPE=kafka
export EVENTMESH_KAFKA_NAMESRV=localhost:9092

./gradlew :eventmesh-runtime:clean :eventmesh-runtime:dist
cd eventmesh-runtime/dist && bash bin/start.sh

Storage-specific keys (all overridable via -D system properties) are documented in eventmesh-configuration.md.

Verify it is up

curl http://localhost:8081/admin/health
# {"status":"UP"}

4. Publish your first event

Applications send standard CloudEvents 1.0 over HTTP. 202 Accepted means the event is durably in the WAL:

curl -X POST "http://localhost:8080/events/publish?topic=orders" \
  -H "Content-Type: application/cloudevents+json" \
  -d '{
    "specversion": "1.0",
    "id": "89010a5a-3c6f-4a1e-9b2d-0f7c1f2e3a4b",
    "source": "/example/producer",
    "type": "com.example.order.created",
    "datacontenttype": "application/json",
    "data": {"orderId": 42, "amount": 99.5}
  }'

5. Subscribe and receive

Register a subscription (there are no consumer groups — EventMesh tracks offsets itself), then receive via one of three transports:

# 1. register: clientId + topic + distribution mode
curl -X POST http://localhost:8080/events/subscribe \
  -H "Content-Type: application/json" \
  -d '{"clientId":"order-svc","topic":"orders","mode":"LOAD_BALANCE"}'

# 2a. HTTP long-polling
curl "http://localhost:8080/events/poll?clientId=order-svc&topics=orders&timeout=30000"

# 2b. after processing, acknowledge so the offset advances (at-least-once)
curl -X POST http://localhost:8080/events/ack \
  -H "Content-Type: application/json" \
  -d '{"clientId":"order-svc","deliveryIds":["..."]}'

Distribution modes:

ModeSemantics
LOAD_BALANCEone subscriber among the group receives each event (partition-key sticky variant available)
BROADCASTevery subscriber receives every event
MULTICASTsubscriber-side predicate filters events per client

SSE and WebSocket push are also available; the raw HTTP forms are:

# SSE — server push over a long-lived HTTP connection
curl -N "http://localhost:8080/events/stream?clientId=order-svc&topics=orders" \r
  -H "Accept: text/event-stream"

# WebSocket — full-duplex server push over the dedicated WS port
# (raw curl works for a one-shot smoke test; real use goes through the SDK)
curl --include --no-buffer \r
  -H "Connection: Upgrade" -H "Upgrade: websocket" \r
  -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGVzdA==" \r
  "http://localhost:8082/events/stream?clientId=order-svc&topics=orders"

The CloudEventsClient Java SDK wraps all three transports — subscribe (long-poll) / subscribeSse / subscribeWs — see the client guide for the trade-offs.

6. Use the SDK instead of raw HTTP (recommended)

CloudEventsClient client = CloudEventsClient.builder()
    .baseUrl("http://localhost:8080")
    .build();
client.init();

// publish
client.publish("orders", CloudEventBuilder.v1()
    .withId(UUID.randomUUID().toString())
    .withSource(URI.create("/order-svc"))
    .withType("com.example.order.created")
    .withData("application/json", "{\"orderId\":42}".getBytes(UTF_8))
    .build());

// subscribe — handler return implies auto-ACK
client.subscribe("orders", "LOAD_BALANCE", event -> {
    System.out.println("got " + event.getType());
});

Full API (request/reply, streaming sessions, lite topics, SSE/WS): see the client guide.

7. Where to go next

  • Configuration reference — every runtime key, per-backend settings
  • Client guide — complete SDK walkthrough
  • Production readiness — verified capabilities, SLOs, runbooks
  • A2A gateway — agent-to-agent messaging (Experimental)
  • Admin API (/admin/*) quick reference: metrics, subscriptions, offsets, clients, client/reject, dlq/replay, dlq/browse, ratelimit, health, connectors, connector-workers on port 8081