Transport choices

Reach every client, on every network, with one protocol.

Corporate firewall? Mobile cellular? IoT bare-metal? The platform speaks WebSocket, SSE, WebTransport, and MQTT. Pick a lane per client. Same wire format.

WebSocket default·HTTP/2 SSE fallback·HTTP/3 WebTransport·MQTT over TLS

4 lanesWebSocket · SSE · HTTP/3 · MQTT
One wireprotobuf envelopes, every lane
Auto-selectSDK picks best available
TLS everywhereon every external lane

When each lane shines

Problems each lane solves.

Smaller cards — these are technical concerns, not product showcases.

Corporate firewall blocks WebSocket

Restrictive proxies strip the Upgrade header. SSE lane rides plain HTTP/2 — looks like any other request.

→ /docs/transport-sse

Cellular tower handoffs drop TCP

WebSocket over TCP renegotiates on every handoff. WebTransport over QUIC migrates the connection — no reconnect.

→ /docs/transport-webtransport

IoT devices can't embed our SDK

Tiny microcontrollers don't speak our protobuf. MQTT lane exposes broadcasts on standard MQTT — they subscribe natively.

→ /docs/transport-mqtt

Why DropOnAir for transport

Same wire, four pipes.

Identical protobuf wire

Every lane carries the same Envelope / CallFrame / GroupEnvelope frames. The transport changes, the bytes don't.

Auto-select at runtime

The SDK queries GET /api/info.transports, intersects with runtime support, picks the best lane. No hard-coded transport per app.

TLS everywhere

Every external lane is TLS — including MQTT on port 8883. The platform never accepts unencrypted external traffic.

Opt-in per app, per session

Pick the lane at init({ transport }). Each platform's SDK supports the lanes that make sense for its runtime.

Comparison

Same wire, four pipes — at a glance.

LaneUnderlyingBest forBrowserBidir
WebSocketTCP/TLSDefault everywhereAllYes
SSE + POSTHTTP/2Restrictive networksAllReceive yes · send via POST
WebTransportUDP / QUICCellular handoffs, modern browsersChromium 97+ · FF 125+Yes
MQTTTCP / TLS · port 8883IoT devices, fleet subscribersn/aSubscribe-only

Choose at init

One option, four backends.

Transport choices in the SDK →

// JS / Web
const client = await initialize({
  appId,
  getUserJwt,
  transport: 'auto',   // ws | sse | wt | auto
});

// Auto resolves to the best lane the runtime supports

What you ship

One SDK call, four transports covered.

  • WebSocket default everywhere
  • SSE auto-fallback for corporate networks
  • HTTP/3 / WebTransport on modern browsers
  • MQTT for IoT-only subscribers
  • Auto-select via /api/info.transports
  • Identical wire format across all lanes
  • TLS on every external lane (WS, SSE, HTTP/3, MQTT)

Pick a lane

Same protocol, every network.

Your SDK call doesn't change. Your customer's network does.