KubeMQ
ConnectorsSTOMPHow-to guides

Connectivity and security

Connecting a STOMP client to KubeMQ — the KUBEMQ_STOMP_URL convention, ports 61613/61614, the CONNECT handshake, heartbeats, and TLS on 61614.

The KubeMQ STOMP connector is an embedded STOMP server inside kubemq-server with its own dedicated listeners — plain TCP 61613 (default) and TLS 61614 (default). An existing STOMP application connects to it by changing only the broker address. This guide covers the connection URL convention, the CONNECT handshake, heartbeats, TLS, and the connection limit.

KUBEMQ_STOMP_URL — the connection convention

The connector reads KUBEMQ_STOMP_URL (default tcp://localhost:61613) and dials it. The URL scheme selects the transport:

export KUBEMQ_STOMP_URL="tcp://localhost:61613"        # default — plain TCP listener (port 61613)
# export KUBEMQ_STOMP_URL="tls://kubemq.example:61614" # TLS listener (port 61614, see below)
SchemeTransportListener (default port)
tcp://plain TCP61613
tls://TLS61614 (active only when the server Security block resolves to TLS)

The connector binds all interfaces (:<port>), not just localhost. Both ports are configurable via the connector configuration.

Verify the listener — do not infer it from a successful server boot. The connector loader is availability-first: a bind failure logs a warning and the server keeps running without STOMP. Confirm the listener is up via the /stomp web dashboard, the kubemq_stomp_connections Prometheus gauge, or GET /api/stomp/connections.

The CONNECT handshake

Every connection opens with the same CONNECT frame and reads the negotiated CONNECTED headers back:

CONNECT
accept-version:1.2          # highest common of 1.0/1.1/1.2; absent/empty → 1.0
heart-beat:10000,10000      # client cx,cy in ms; server advertises sx=sy=HeartbeatMs (default 10000)
login:my-app                # freeform (session id fallback when no JWT claims)
passcode:                   # empty/any in the default no-auth mode

^@

The CONNECTED reply carries:

HeaderValue
versionthe negotiated version (1.0 / 1.1 / 1.2)
heart-beatthe server's advertised sx,sy (both = HeartbeatMs), not the negotiated effective values
sessionthe derived client id (see Authentication)
serverKubeMQ/<version>

CONNECTED headers are never escaped (handshake exemption). The handshake order is: version negotiation → broker-ready gate → max-connections check → auth → derive client id → heartbeat negotiation → send CONNECTED.

accept-version:1.2 is recommended. See Protocol versions for the negotiation rules and the per-version feature matrix.

Heartbeats and the 2x dead-peer cutoff

Heartbeats keep the TCP connection alive and let the connector detect a dead peer.

  • The client sends heart-beat:cx,cy (ms). The server advertises sx = sy = HeartbeatMs (default 10000; 0 disables the server side).
  • Effective client→server interval = maxNonZero(cx, sy); server→client = maxNonZero(sx, cy) — where maxNonZero(a, b) is 0 if either side is 0 (that direction is disabled), otherwise max(a, b).
  • Parsing is lenient: a missing, non-numeric, negative, or 3-field value becomes 0,0.

The dead-peer cutoff is 2x the negotiated client→server interval. The watchdog force-closes the connection (audited as client.timeout) if no inbound bytes arrive within that window. Any inbound byte — a real frame or a bare \n heartbeat — refreshes liveness. The server sends a heartbeat LF only when it has written nothing for at least half the server→client interval.

Recommendation: send heart-beat:10000,10000 (matches the server default). With a 10 s client→server interval the cutoff is 20 s — a client must send a frame or a bare \n before that window elapses.

TLS

TLS is a transport swap — the STOMP protocol on top is unchanged. Point KUBEMQ_STOMP_URL at tls://host:61614 and configure the server Security block; the STOMP frames are identical.

export KUBEMQ_STOMP_URL="tls://kubemq.example.com:61614"
  • The TLS listener is the default port 61614 (tls://...).
  • It is active only when the TLS port is configured and the server-wide Security block resolves to non-nil TLS. If the Security mode is none, the TLS port is silently skipped.
  • TLS has no STOMP-specific config. The certificate material, mTLS, and minimum version all come from the server-wide Security block — the connector owns only whether the TLS port is open. mTLS requires and verifies the client certificate; the minimum is TLS 1.2.

For the shared KubeMQ JWT model and TLS/mTLS concepts across connectors, see Auth & security.

WebSocket is not supported in V1

The connector is raw TCP only. STOMP-over-WebSocket is a documented future listener path, not a current feature. The popular browser/Node client @stomp/stompjs speaks STOMP only over WebSocket, so it cannot connect to the raw-TCP listener directly. The JavaScript/TypeScript examples therefore use stompit (raw TCP).

Connection limit

The connector enforces a maximum connection count (default 1000; 0 = unlimited). The slot is counted at accept — a raw TCP socket that never sends CONNECT still consumes a slot — but the over-limit ERROR "connection limit reached" is deferred to the handshake so the client receives a proper frame.

Errors are terminal

Every protocol error produces an ERROR frame followed by a socket close. The message is sanitized — internal error text never crosses the wire. Treat every ERROR frame as terminal in client code, and reconnect if appropriate.

Was this page helpful?

On this page