Sending Messages

1. Sending Text Messages

MethodAccepts
ws.send(string)UTF-8 text frame (opcode 0x1)
ws.send(ArrayBuffer)Binary frame (0x2)
ws.send(TypedArray)Binary frame
ws.send(Blob)Binary frame

Example: Text send

ws.send("hello server");
Warning: Calling send() when readyState !== OPEN throws InvalidStateError.

2. Sending JSON Data

Example: Typed message envelope

function emit(type, payload) {
  ws.send(JSON.stringify({ "type": type, "id": crypto.randomUUID(), "ts": Date.now(), "payload": payload }));
}
emit("chat.message", { "room": "general", "text": "hi" });
FieldPurpose
typeDispatch key
idCorrelation / dedup
tsClient timestamp
payloadType-specific data

3. Checking Buffer Amount

Example: Backpressure-aware send

const MAX_BUFFER = 1 * 1024 * 1024; // 1 MB
function safeSend(data) {
  if (ws.bufferedAmount > MAX_BUFFER) return false;
  ws.send(data);
  return true;
}
PropertyDetail
bufferedAmountBytes queued in user agent, not yet on wire
UpdatedAfter each send()
Reaches 0When fully flushed to network

4. Queuing Messages

Example: Pre-open queue

const queue = [];
function send(msg) {
  if (ws.readyState === WebSocket.OPEN) ws.send(msg);
  else queue.push(msg);
}
ws.addEventListener("open", () => { while (queue.length) ws.send(queue.shift()); });
StrategyWhen
FIFO queueOrder matters
CoalesceLatest-state wins (e.g. cursor)
Drop oldestBounded memory

5. Validating Message Size

LimitTypical
Browser per-frameUnlimited (memory-bound)
ws library default (Node)100 MB (maxPayload)
Nginx client_max_body_sizeN/A (different mechanism)
Recommended≤ 64 KB / msg

6. Handling Send Errors

Example: Guarded send

try { ws.send(data); }
catch (err) {
  if (err.name === "InvalidStateError") queue.push(data);
  else throw err;
}
ErrorMeaning
InvalidStateErrorSocket not OPEN
SyntaxErrorInvalid UTF-8 in string

7. Sending Binary Data

Example: Send ArrayBuffer

const buf = new ArrayBuffer(4);
new DataView(buf).setUint32(0, 0xDEADBEEF);
ws.send(buf);
TypeFrame
ArrayBufferBinary (0x2)
BlobBinary
Uint8Array etc.Binary

8. Sending Typed Arrays

Typed ArrayBytes / Element
Uint8Array1
Int16Array2
Float32Array4
BigInt64Array8
Note: Endianness is little-endian on most platforms; encode explicitly with DataView for cross-platform protocols.

9. Implementing Message Batching

Example: Time-window batcher

let pending = [], timer = null;
function batchSend(msg) {
  pending.push(msg);
  timer ??= setTimeout(() => {
    ws.send(JSON.stringify({ "type": "batch", "items": pending }));
    pending = []; timer = null;
  }, 20);
}
TriggerUse
Time windowEven update rate
Count thresholdBounded latency
Size thresholdBandwidth efficient

10. Compressing Messages

ApproachTrade-off
permessage-deflate (auto)Negotiated extension; CPU cost
App-level gzip/brotliManual; better control
Binary format (MessagePack/Protobuf)Smaller than JSON+deflate often