From HTTP Handshake to Connection
A Socket.IO connection doesn't start as a WebSocket — it begins with a regular HTTP GET request to the server's Engine.IO endpoint (/socket.io/), which performs a handshake exchanging a session ID and supported transport options. By default, the client starts with HTTP long-polling and then attempts to upgrade to a WebSocket transport if the server supports it; this two-step approach exists because some corporate proxies and older browsers block raw WebSocket upgrades outright, so falling back to polling guarantees the connection can be established somewhere, even if it's less efficient. Once the handshake and (optional) transport upgrade succeed, the server fires the connection event on io, and the client's socket receives a connect event with a newly assigned socket.id.
Cricket analogy: It's like a toss before the match — first there's a preliminary coin-flip handshake (HTTP polling) to establish who bats first, and only after that formality is settled does the actual game (WebSocket) begin in earnest.
Disconnection and its reasons
The disconnect event fires on both client and server when a connection ends, and its callback receives a reason string that explains why. Common reasons include 'io server disconnect' (the server explicitly called socket.disconnect()), 'io client disconnect' (the client explicitly called socket.disconnect()), 'ping timeout' (the client failed to respond to the server's heartbeat within the configured window, suggesting a dead or very slow connection), and 'transport close' (the underlying connection, e.g. the TCP socket or WebSocket, was closed, often due to network changes). This reason matters operationally: a 'ping timeout' typically warrants automatic client-side reconnection, whereas 'io server disconnect' means the server intentionally kicked the client (e.g. after a ban), and the client should NOT automatically reconnect in that case — Socket.IO's client actually enforces this by not auto-reconnecting only for that specific reason.
Cricket analogy: It's like the different reasons a batter's innings ends — run out (an involuntary external event, like ping timeout), retired hurt (self-initiated, like client disconnect), or given out by the umpire's decision (like server disconnect) — each carries different implications for what happens next.
Automatic reconnection
The Socket.IO client has built-in reconnection logic enabled by default (reconnection: true). After most disconnect reasons, it automatically retries the connection with exponential backoff, controlled by options like reconnectionAttempts, reconnectionDelay, and reconnectionDelayMax. During this process it emits its own sequence of events on the socket.io manager: reconnect_attempt before each try, reconnect once a retry succeeds (with the attempt number as an argument), and reconnect_failed if all attempts are exhausted. Because reconnection creates a brand-new underlying connection, socket.id typically changes after a reconnect (unless you've configured session-ID-based connection state recovery, a newer Socket.IO feature that can restore missed events and room membership after a brief disconnect), so application code that keys data off socket.id must handle this rather than assuming it's stable for a client's entire session.
Cricket analogy: It's like a rain-delayed match resuming under Duckworth-Lewis rules — play automatically restarts once conditions allow (reconnection), but the match state (overs, target) has to be explicitly recalculated rather than assumed to be exactly as it was.
import { io } from 'socket.io-client';
const socket = io('https://app.example.com', {
reconnection: true,
reconnectionAttempts: 10,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
});
socket.on('connect', () => {
console.log('connected with id', socket.id);
});
socket.on('disconnect', (reason) => {
console.log('disconnected:', reason);
if (reason === 'io server disconnect') {
// server intentionally kicked us — do not auto-reconnect
socket.connect();
}
// for other reasons, the client already auto-reconnects
});
socket.io.on('reconnect_attempt', (attempt) => {
console.log('reconnect attempt #', attempt);
});
socket.io.on('reconnect', (attempt) => {
console.log('reconnected after', attempt, 'attempts, new id:', socket.id);
});You can listen for connection state recovery success via socket.recovered (a boolean) right after a 'connect' event fires — when true, Socket.IO has restored the socket's prior rooms and replayed any events missed during a brief disconnect, avoiding the need to manually resync state.
Never assume socket.id is a stable, long-lived user identifier — it changes on every reconnect by default. Use your own application-level user ID or auth token to correlate a client across reconnects, and store any per-user state (like room membership) so it can be reapplied in your 'connect' handler after each reconnection.
- Connections start with an HTTP handshake and may upgrade to WebSocket transport afterward.
- The 'connect' event fires on the client with a new socket.id once the handshake succeeds.
- The 'disconnect' event provides a reason string like 'ping timeout' or 'io server disconnect'.
- The client auto-reconnects by default for most disconnect reasons, but not after an intentional server disconnect.
- Reconnection attempts use exponential backoff, configurable via reconnectionDelay and reconnectionDelayMax.
- socket.id typically changes after every reconnect, so it shouldn't be used as a stable user identifier.
- Connection state recovery can restore rooms and missed events after brief disconnects, indicated by socket.recovered.
Practice what you learned
1. What is the first step in establishing a Socket.IO connection?
2. What does a disconnect reason of 'io server disconnect' mean, and how does the client respond by default?
3. What typically happens to socket.id after a client reconnects?
4. Which client option controls the maximum delay between reconnection attempts?
5. What does socket.recovered being true after a 'connect' event indicate?
Was this page helpful?
You May Also Like
Broadcasting Events
Learn how to send events to groups of clients at once using io.emit, broadcast.emit, and rooms, the mechanisms that power chat rooms, live dashboards, and multiplayer presence.
Emitting and Listening to Events
Learn how Socket.IO's event-based API lets clients and servers send named messages to each other using emit and on, the foundation of every real-time feature.
Acknowledgements and Callbacks
Learn how Socket.IO acknowledgements let the sender of an event know it was received and processed, turning fire-and-forget emits into request/response style calls.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics