The hub WebSocket (/hub/ws) is the internal streaming endpoint exposed by mx-notifier. It uses the same binary protobuf framing protocol that the MultiversX node uses to push data to mx-notifier. Consumers connect, send a subscription message, and receive a continuous stream of matching normalized events.
Endpoint
ws://<notifier-host>/hub/ws
The endpoint is binary-only. All frames β inbound (consumer to mx-notifier) and outbound (mx-notifier to consumer) β are binary WebSocket frames carrying serialized WsMessage protobuf messages.
Do not send text frames to this endpoint. The server expects binary frames exclusively. Text frames are discarded or cause a protocol error depending on server configuration.
Frame format
Every frame is a serialized WsMessage protobuf message:
messageWsMessage {uint32version=1;// Protocol version; must be >= 1boolwith_acknowledge=2;// If true, sender expects an ACK replyuint64counter=3;// Monotonically increasing frame counterint32type=4;// 1 = ACK, 2 = PAYLOADstringtopic=5;// Non-empty for PAYLOAD framesbytespayload=6;// Serialized event data}
Field reference
Field
Type
Required
Description
version
uint32
Yes
Protocol version. Must be >= 1. Frames with version 0 are rejected.
with_acknowledge
bool
No
When true, the receiver must send an ACK frame with the same counter value before sending the next payload. Defaults to false.
counter
uint64
Yes
Monotonically increasing per-connection frame counter. Used to correlate ACK messages with their corresponding PAYLOAD frames.
type
int32
Yes
1 = ACK frame. 2 = PAYLOAD frame.
topic
string
Conditional
Non-empty string identifying the event type. Required for PAYLOAD frames (type 2). Empty for ACK frames.
payload
bytes
Conditional
Serialized event data. Present for PAYLOAD frames. Empty for ACK frames.
Message types
PAYLOAD (type = 2)
PAYLOAD frames carry actual event data. The topic field identifies the event category. The payload field contains a serialized protobuf message whose schema depends on the topic.
A PAYLOAD frame is valid when:
version >= 1
type == 2
topic is a non-empty string
payload is non-empty
ACK (type = 1)
ACK frames are control messages for flow acknowledgement. When a PAYLOAD frame arrives with with_acknowledge = true, the receiver must reply with an ACK frame carrying the same counter value before the sender transmits the next frame.
An ACK frame sets:
type = 1
counter = the counter value from the PAYLOAD being acknowledged
topic and payload are empty
Acknowledgement protocol
When with_acknowledge is true on a received PAYLOAD frame, mx-notifier waits for the consumer to send an ACK before delivering the next event. This is a stop-and-wait flow control mechanism.
Sequence for acknowledged delivery:
Most consumers should leave with_acknowledge = false and rely on the server-side backpressure mechanisms described below. Use acknowledged delivery only when the consumer must guarantee ordered, exactly-once processing before the next event arrives.
Frame validation rules
mx-notifier silently drops frames that fail any of the following rules:
Rule
Condition
Version check
version >= 1
Type check
type is 1 (ACK) or 2 (PAYLOAD)
Topic required for payload
PAYLOAD frames must have a non-empty topic
Subscribing
After connecting, send a SubscribeEvent protobuf message serialized inside a WsMessage PAYLOAD frame (topic: subscribe). The SubscribeEvent declares the filter criteria for the events you want to receive.
See filtering.md for the full SubscribeEvent structure, match level options, and code examples.
Backpressure
mx-notifier applies two layers of backpressure to protect the server under high load:
Global semaphore β a server-wide limit caps concurrent in-flight event deliveries across all hub connections. When the limit is reached, new events queue until capacity frees.
Per-connection semaphore β each hub connection has its own concurrency limit. If a consumer reads frames slowly, its per-connection semaphore fills and new events targeting that connection are held until the consumer catches up.
If a consumer consistently fails to drain its receive buffer, the server closes the connection when the per-connection queue reaches its maximum depth. Consumers must read frames promptly and avoid blocking the receive loop with expensive processing. Offload heavy work to a separate goroutine or thread.
JavaScript example
The following example uses protobufjs to connect, decode a PAYLOAD frame, and send an ACK.
mx-notifier auto-reconnects to the MultiversX node if the upstream WebSocket drops. The hub WebSocket connection to consumers remains open during node reconnection, but event delivery pauses until the upstream connection is restored.