# TR-369 WebSocket vs MQTT vs STOMP: how do the USP transports compare?

Dodderware engineering team · Published 2026-10-28 · https://blog.dodderware.com/usp-mtp-websocket-mqtt-stomp/

[Leer en español](https://blog.dodderware.com/es/mtp-usp-websocket-mqtt-stomp/)

> **Short answer:** TR-369 defines four Message Transfer Protocols (MTPs) to carry USP Records. WebSocket links an Agent and a Controller directly over one long-lived session. STOMP and MQTT route Records through a broker, by destination or by Topic. The UNIX Domain Socket MTP connects an Agent and a Controller running as separate processes on the same device. CoAP was obsoleted in USP 1.3.

Before an Agent and a Controller can exchange a single USP Message, they have to agree on how it travels. TR-369
calls that layer the **Message Transfer Protocol (MTP)** and defines four of them. The one you pick decides whether
your devices need a broker, how they announce who they are and how they behave after an outage. This guide compares
WebSocket, STOMP, MQTT and UNIX Domain Socket using only what the specification says.

## What is a Message Transfer Protocol?

An MTP is “the protocol at a layer below USP that carries a Message”, for example WebSocket (§1.4). The USP Record is
the MTP payload (§4.1.3), so every binding answers the same questions: how to connect, how to carry a Record and how
to report a failure. Our [guide to TR-369](https://blog.dodderware.com/what-is-tr-369/) explains how Records and Messages nest.

A few rules apply to every MTP (§4.1). Agents and Controllers may support more than one, and Endpoints always respond
on the MTP where the Message was received (§4.1.1). Once the channel is up, an Agent that can do so sends the Connect
Record for the MTP in use, such as `WebSocketConnectRecord` or `MQTTConnectRecord` (R-MTP.6), and it should send a
`DisconnectRecord` before leaving (R-MTP.7). Since USP 1.2, Record problems are reported with USP Records instead of
MTP-specific messages, using error codes 7100 to 7199 (§4.1.4, Issue History).

## How do the four MTPs compare?

| MTP                       | Path between Endpoints                 | Sender identifies itself with         | Payload marked by                           | Transport security            |
| ------------------------- | -------------------------------------- | ------------------------------------- | ------------------------------------------- | ----------------------------- |
| WebSocket (§4.3)          | One direct session per pair            | `eid` in the handshake request URI    | The `v1.usp` subprotocol, binary frames     | TLS (R-WS.22)                 |
| STOMP (§4.4)              | Through a STOMP server, by destination | `endpoint-id` header                  | `content-type: application/vnd.bbf.usp.msg` | TLS 1.2 or later (R-STOMP.36) |
| MQTT (§4.5)               | Through an MQTT server, by Topic       | `usp-endpoint-id` User Property (5.0) | Content Type `usp.msg` (5.0)                | TLS 1.2 or later (R-MQTT.48)  |
| UNIX Domain Socket (§4.6) | Between processes on one device        | Handshake TLV (Type 1)                | USP Record TLV (Type 3)                     | Optional TLS (§4.6.4)         |

The split that matters most is direct versus brokered. With WebSocket, the two Endpoints hold the session themselves.
With STOMP and MQTT, each Endpoint holds a session with a server that routes Records on its behalf.

## How does the WebSocket MTP work?

The WebSocket binding uses RFC 6455, with long-lived sessions reused for later Records (§4.3, §4.3.2). An Agent must
be able to open a session and to accept one from a Controller (R-WS.5, R-WS.6). In general the Agent opens it, so it
does not expose an open port toward the Internet for security reasons, and two Endpoints use at most one open session
(§4.3.2, R-WS.4).

The handshake carries two USP details (§4.3.2.1):

- **The subprotocol.** The client sends `v1.usp` in the `Sec-WebSocket-Protocol` header and the server returns it
  (R-WS.9 to R-WS.11). If it does not come back, the client does not establish the session (R-WS.12).
- **The client’s Endpoint ID.** With TLS, the server cannot tell who is connecting without looking inside the
  certificate, so the client adds `eid=` and its Endpoint ID to the query of the request URI (R-WS.10b). The
  requirement to use a WebSocket Extension instead was removed in USP 1.3 (R-WS.10a).

Records travel in binary data frames (R-WS.14). Senders should not fragment them, but receivers must handle fragments
(R-WS.14a, R-WS.14b). If a Record cannot be extracted, for example from a text frame, the receiver closes the connection
with status code 1003 (R-WS.16). Agents keep the session alive with Ping and Pong frames on a configurable interval
(R-WS.17, R-WS.18).

> **Did you know?**
>
> After an outage, an Agent does not reconnect on a fixed timer. With the factory defaults, a 5-second minimum wait and a
> multiplier of 2000, the first retry waits 5 to 10 seconds and the window doubles each time. From the tenth retry on, the
> Agent waits between 2,560 and 5,120 seconds, about 43 to 85 minutes. A Controller can tune both values when the Agent
> implements `SessionRetryMinimumWaitInterval` and `SessionRetryIntervalMultiplier` (R-WS.19).

> **Where DWS Support fits**
>
> WebSocket is the MTP DWS Support uses today. Its native USP controller connects to Agents over WebSocket, ws or wss,
> and exchanges USP Records with them. It was developed and tested against obuspa, the Broadband Forum’s open-source USP
> Agent, and the same console drives each device over TR-069 or TR-369, chosen per device.
>
> [See DWS Support](https://dodderware.com/products/dws-support/)

## How do STOMP and MQTT use a broker?

Both brokered bindings follow the same basic steps: negotiate TLS if configured, connect to the server, subscribe, then
send USP Records (§4.4, §4.5).

1. **STOMP or MQTT client** (Agent): Subscribes to its own destination or Topic and adds a reply-to address to everything it sends.
2. **STOMP or MQTT server** (Broker): Authenticates each client and limits what it may subscribe to.
   - STOMP: destination
   - MQTT: Topic
3. **STOMP or MQTT client** (Controller): Sends to the Agent’s destination or Topic and answers on the reply-to address.

*Brokered MTPs. Agent and Controller each keep their own session with the STOMP or MQTT server, which routes every USP Record by destination or Topic. Diagram by Dodderware, based on TR-369 §4.4 and §4.5.*

Because there is no direct session, everything sent through the broker says where to answer. STOMP uses a
`reply-to-dest` header (R-STOMP.21). MQTT requires a “reply to” Topic in every PUBLISH packet: in the Response Topic
property on MQTT 5.0, or after `/reply-to=` at the end of the Topic Name on MQTT 3.1.1 (R-MQTT.22 to R-MQTT.24). The
broker can also tell an Agent where to listen: a `subscribe-dest` header on STOMP, a `subscribe-topic` User Property on
MQTT 5.0 (R-STOMP.6, §4.5.2).

The broker carries real duties. A STOMP server must authenticate clients and let each one subscribe only to its own
destination (R-STOMP.34). An MQTT server must authenticate clients and support an Access Control List that restricts
the Topics each one can use (R-MQTT.42).

- **STOMP**, the Simple Text Oriented Message Protocol, is used in version 1.2 (§4.4). USP Endpoints send the
  Endpoint ID in an `endpoint-id` header (R-STOMP.4), subscribe with `ack` set to “auto”, and never send transaction
  or acknowledgement frames (R-STOMP.17, R-STOMP.26, R-STOMP.27).
- **MQTT**, Message Queuing Telemetry Transport, joined USP in 1.1 (Issue History). Clients must implement MQTT 5.0
  and may add 3.1.1 (R-MQTT.1, R-MQTT.2). Version 5.0 matters because 3.1.1 gives a client no simple way to pass its
  Endpoint ID to the server, and gives the server no way to tell the client its “reply to” Topic (§4.5.1.1). Agents
  must support MQTT over TCP, and MQTT over WebSockets is allowed (R-MQTT.3). Endpoints must support QoS 0 and 1
  (R-MQTT.20), and since USP 1.5 they should support ALPN in the TLS handshake (R-MQTT.48a).

In DNS-SD records, a brokered Endpoint advertises the broker’s address, not its own (R-STOMP.32, R-MQTT.38). See
[how a USP Agent finds its Controller](https://blog.dodderware.com/usp-discovery-dhcp-mdns/).

## When does the UNIX Domain Socket MTP make sense?

When the Agent and the Controller live on the same box. This internal MTP, added in USP 1.3, connects “separate
processes within a single device” (§4.6). The socket is tied to a local file path instead of a host and port, each
Endpoint acts as server or client but not both, and nothing needs advertising over mDNS (§4.6.1).

- **Frame**: A Header, then one or more TLV fields. (Sync: 0x5f 0x55 0x53 0x50 (“_USP”), Length of the rest: 4 bytes)
  - **TLV field**: Type 1 Handshake, 2 Error, 3 USP Record, 4 Password. (Type: 1 byte, Length: 4 bytes, Value)
    - **USP Record**: The Protocol Buffers binary encoding of the Record, carried as the value of a Type 3 TLV.

*Inside a UNIX Domain Socket Frame. Diagram by Dodderware, based on TR-369 §4.6.1.3.*

Both sides exchange Handshake TLVs with their Endpoint IDs before any Record, and a client that gets no answer within
30 seconds closes the connection (R-UDS.16 to R-UDS.18). When a connection drops, the client retries within a random 1
to 5 seconds (R-UDS.5). Encryption is not required, though TLS has been an option since USP 1.4, and USP 1.5 added the
Password TLV for shared-secret authentication (§4.6.4, Issue History).

## Which MTPs need TLS?

The baseline is R-MTP.0: an MTP “MUST use secure transport when USP Messages cross inter-network boundaries” (§4.1.2).
Within an end user’s LAN, MTP security may not be necessary. MTPs over TCP are expected to implement at least TLS 1.2,
and when TLS is used, the Agent must require an X.509 certificate from its peer (§4.1.2, R-MTP.1).

MTP bindings provide point-to-point security, so on a brokered MTP that TLS protects each hop to the broker, not the
whole path between Agent and Controller (§6.4). For that, USP has Trusted Brokers and end-to-end Secure Message
Exchange, covered in [TR-369 security](https://blog.dodderware.com/tr-369-security/).

## Did you know?

- A USP WebSocket session only opens if the server echoes the v1.usp subprotocol in its Sec-WebSocket-Protocol header. (TR-369 §4.3.2.1, R-WS.12)
- USP Endpoints that use MQTT clients must implement MQTT 5.0. Support for MQTT 3.1.1 is optional. (TR-369 R-MQTT.1, R-MQTT.2)
- When a WebSocket frame carries a USP Record that cannot be extracted, the receiver closes the connection with status code 1003. (TR-369 R-WS.16)
- Every UNIX Domain Socket Frame starts with the four bytes 0x5f 0x55 0x53 0x50, which spell “_USP”. (TR-369 R-UDS.8)
- The UNIX Domain Socket MTP arrived in USP 1.3, and MQTT in USP 1.1. (TR-369 Issue History)

## Questions people ask

### Which transports does USP support?

TR-369 defines four Message Transfer Protocols, WebSocket, STOMP, MQTT and UNIX Domain Socket. A fifth, CoAP, was deprecated in USP 1.2 and obsoleted in USP 1.3 (§4.2).

### What is the WebSocket subprotocol for USP?

It is v1.usp. The WebSocket client sends it in the Sec-WebSocket-Protocol header, the server returns it, and a client that does not get it back does not establish the session (§4.3.2.1, R-WS.9, R-WS.12).

### Does USP over MQTT require MQTT 5.0?

Yes. USP Endpoints that use MQTT clients must implement MQTT 5.0 and may also implement MQTT 3.1.1. MQTT servers must implement 5.0 and should implement 3.1.1 (R-MQTT.1, R-MQTT.2, R-MQTT.39, R-MQTT.40).

### Who opens the WebSocket connection, the Agent or the Controller?

Either one. An Agent must be able to originate a WebSocket session and to accept one from a Controller, and two Endpoints use at most one open session. In general the Agent opens it, so it does not expose an open port toward the Internet (§4.3.2, R-WS.4 to R-WS.6).

### Is TLS mandatory on USP transports?

An MTP must use secure transport when USP Messages cross inter-network boundaries, and MTPs that run over TCP are expected to implement at least TLS 1.2 (§4.1.2, R-MTP.0). The UNIX Domain Socket MTP stays inside the device, so TLS is optional there (§4.6.4).

### Can an Agent use more than one MTP?

Yes. Agents and Controllers may support several MTPs, an Agent can be configured to reach one Controller over more than one, and responses always go back on the MTP the Message arrived on (§4.1.1).

## Sources

- Broadband Forum, TR-369 – The User Services Platform, Issue 1 Amendment 5 (USP 1.5), January 2026.
- Dodderware, DWS Support product and engineering documentation.
- §1.4, §4, §4.1.1: MTP definition, Message Transfer Protocols, supporting multiple MTPs
- §4.1.2: Securing MTPs (R-MTP.0, R-MTP.1)
- §4.1.3, §4.1.4, §4.1.5: USP Record encapsulation, USP Record errors, Connect and Disconnect Records
- §4.2: The obsoleted CoAP binding
- §4.3: WebSocket binding (R-WS.4 to R-WS.22)
- §4.4: STOMP binding (R-STOMP.2 to R-STOMP.36)
- §4.5: MQTT binding (R-MQTT.1 to R-MQTT.48a)
- §4.6: UNIX Domain Socket binding (R-UDS.1 to R-UDS.25)
- Issue History: MQTT added in USP 1.1, UNIX Domain Socket in USP 1.3, ALPN for MQTT in USP 1.5

[Read the TR-369 specification](https://usp.technology/specification/index.htm)

TR-369 © The Broadband Forum. All rights reserved. Quoted briefly and paraphrased for commentary; the diagrams are Dodderware’s own.

---

**Manage TR-069 and TR-369 devices from one console.** DWS Support brings every ONT and home router into one web console, whichever protocol it speaks: TR-069 through GenieACS or a built-in ACS, TR-369 through a native USP controller. Self-hosted on your infrastructure. [Request a demo](https://dodderware.com/products/dws-support/#get-started)
