Browsers add their own lifecycle around a WebSocket. This page covers what actually happens with tabs, unloads, and background pages, so presence timing and connection counts never surprise you.
Every tab is its own connection
Browser tabs are sandboxed from each other, so each tab that creates a Realtime client holds its own WebSocket. A user with three tabs open is three concurrent connections against your plan’s limit, and three presence members when each tab enters presence, distinguishable by their connectionId. The SDK doesn’t share connections across tabs, and doesn’t install any page lifecycle handlers on your behalf.
If per-user presence matters more than per-tab, key your UI on clientId rather than counting members, the way chat occupancy counts presenceMembers separately from connections.
Closing a tab
When a tab closes or navigates away normally, the browser shuts the WebSocket down with a goodbye, and the service processes it immediately: the connection ends and its presence members leave at once. Other members see the leave right away. You don’t need a beforeunload handler for this, the browser’s own socket teardown is the signal.
Call realtime.close() yourself when the user signs out while staying on the page, since no unload happens then.
Dying silently
A tab that vanishes without a goodbye, a crashed browser, a dropped network, a laptop lid, is detected rather than announced. The service probes quiet connections and gives up after roughly 40 seconds, then holds presence membership for a further 15-second grace window in case the same connection resumes. So a silently killed tab’s presence leave reaches other members after about a minute, while a brief network blip that reconnects inside the window shows no leave at all.
Design for both ends: joins and clean exits are instant, silent deaths take up to a minute to show. A UI that must react faster than that should use its own heartbeat messages rather than presence.
Background tabs
Browsers throttle timers in background tabs and may suspend pages entirely, including back/forward-cache navigations and features like Chrome’s Memory Saver. When a suspended page killed the socket, the SDK finds out on resume and reconnects with its normal backoff, re-attaching channels and re-entering presence as described in Connections. From the rest of the room’s point of view, a long-suspended tab looks like the silent death above, then a rejoin.