Script Valley
WebSockets & Real-Time Applications
Browser WebSocket APILesson 2.5

How to close a WebSocket connection gracefully

close() method, close code semantics, reason string, initiating close from client, server-initiated close, CLOSING state handling, cleanup checklist

Closing a WebSocket the Right Way

Calling ws.close() without arguments closes with code 1000. Always pass a code and reason in production for debuggability:

// Normal closure — user logged out ws.close(1000, 'User logged out'); // Going away — page unload ws.close(1001, 'Page navigating away'); // Application error ws.close(4000, 'Auth token expired');

Codes 4000–4999 are reserved for application-defined use. Use them to communicate application state to the client in the close reason.

Cleanup Checklist

Forgetting cleanup causes memory leaks and phantom reconnects. Every WebSocket setup should have a paired teardown:

function cleanup(ws) { clearInterval(heartbeatTimer); clearTimeout(pongTimer); clearTimeout(retryTimeout); ws.onopen = null; ws.onmessage = null; ws.onerror = null; ws.onclose = null; if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) { ws.close(1000, 'Cleanup'); } }

In React, call cleanup in the useEffect return function. In Vue, call it in onUnmounted. In plain JS, call it on beforeunload.