Managing Connection Lifecycle

1. Handling Connection Open

StepAction
1Reset reconnect attempt counter
2Send auth (if message-based)
3Resume subscriptions / state
4Start heartbeat timer
5Flush outbound queue

2. Handling Connection Close

Example: Close inspection

ws.addEventListener("close", (e) => {
  console.log({ code: e.code, reason: e.reason, clean: e.wasClean });
  stopHeartbeat();
  if (shouldReconnect(e.code)) scheduleReconnect();
});
CodeReconnect?
1000 NormalNo (intentional)
1001 Going AwayYes
1006 AbnormalYes (with backoff)
4401 Unauthorized (custom)No (refresh token first)

3. Understanding Close Codes

CodeNameMeaning
1000Normal ClosureSuccessful completion
1001Going AwayServer shutdown / page navigation
1002Protocol ErrorSpec violation
1003Unsupported Datae.g. binary on text-only endpoint
1005No StatusReserved — no code received
1006AbnormalConnection dropped without close frame
1007Invalid PayloadBad UTF-8 in text frame
1008Policy ViolationGeneric policy reject
1009Message Too BigPayload exceeds limit
1010Mandatory ExtensionServer didn't accept required ext
1011Internal ErrorServer fault
1012Service RestartReconnect later
1013Try Again LaterServer overloaded
1015TLS HandshakeReserved
3000-3999RegisteredLibrary/framework codes
4000-4999ApplicationFree for your app

4. Sending Close Frame

Example: Close with code/reason

ws.close(1000, "user-logout");
// 4xxx app codes
ws.close(4001, "auth-expired");
ConstraintDetail
code1000 or 3000-4999 from app
reasonUTF-8 string ≤ 123 bytes
IdempotentSubsequent calls ignored

5. Handling Abnormal Closure

Note: Code 1006 means no Close frame was exchanged — typically network loss, proxy timeout, or server crash. Always retry with backoff.
CauseAction
Network lossBackoff reconnect
Idle timeoutAdd heartbeat
Server crashRetry; check health endpoint

6. Implementing Graceful Shutdown

Graceful Shutdown Sequence

  1. Stop accepting new outbound messages
  2. Flush bufferedAmount to 0
  3. Stop heartbeat timer
  4. Call ws.close(1000, reason)
  5. Await close event (with timeout)
  6. Release references / listeners
PhaseDetail
DrainWait for buffer to empty
CloseSend Close frame with code 1000
TimeoutForce-discard after ~3s

7. Cleaning Up Resources

ResourceCleanup
Event listenersAbortController.abort()
TimersclearInterval/clearTimeout
Pending requestsReject with abort reason
SubscriptionsClear local registry

8. Tracking Connection Duration

Example: Uptime tracking

let openedAt = 0;
ws.addEventListener("open", () => { openedAt = Date.now(); });
ws.addEventListener("close", () => {
  metrics.observe("ws_duration_ms", Date.now() - openedAt);
});
MetricUse
Connect timeHandshake latency
UptimeConnection stability
Reconnect countNetwork quality signal

9. Implementing Connection Pooling

StrategyDetail
One per tabUse BroadcastChannel/SharedWorker
MultiplexedOne socket, message channel field
Per-featureSeparate sockets for isolation

10. Handling Server Shutdown

Server ActionCodeClient Action
Rolling deploy1001 Going AwayReconnect
Maintenance1012/1013Backoff longer
Crash1006Backoff + circuit breaker