v149 · platform behavior · shipped
Disconnect WebSockets on BFCache Entry
Pages with active WebSocket connections can now enter the back/forward cache. Chrome 149 closes open connections when the page is cached, fires the close event, and expects apps to reconnect when pageshow fires with persisted: true.
close event work correctly; apps that assume a connection is always live will stall after a back/forward navigation.
at a glance
| Shipped in | Chrome 149 (desktop + Android) |
|---|---|
| Status | Browser behavior change (no new API) |
| Flag | None |
| Spec | WHATWG HTML PR #12349 |
| Web Platform Tests | websockets/back-forward-cache-closes-open-websocket-connection |
| ChromeStatus | 5068439115923456 — Disconnect WebSockets on BFCache entry |
why it exists
The back/forward cache (BFCache) stores a page's full live state in memory so that back-button and forward-button navigation is nearly instant. Until Chrome 149, any page with an active WebSocket connection was disqualified from BFCache — the browser couldn't safely freeze a live connection. Popular web apps like Notion, Figma, and Slack Web all keep persistent WebSocket connections, so BFCache was effectively unavailable for them, hurting navigation performance for millions of users.
Chrome 149 resolves the incompatibility by closing WebSocket connections when the page enters BFCache rather than blocking caching entirely. Well-written apps already handle the close event to reconnect on unexpected disconnections (network drops, server restarts). Those apps get BFCache for free.
what changes
| Before Chrome 149 | A page with any open WebSocket is ineligible for BFCache. Navigating away and pressing Back causes a full page reload. |
|---|---|
| Chrome 149+ | On BFCache entry, Chrome closes open WebSocket connections. The close event fires on each socket. The page is stored in the cache. |
| On BFCache restore | pageshow fires with event.persisted === true. The app's existing close-and-reconnect logic (if present) reopens the connection. |
example
Reconnect on BFCache restore
let ws;
function connect() {
ws = new WebSocket("wss://example.com/live");
ws.addEventListener("message", handleMessage);
ws.addEventListener("close", () => {
// Handles network drops, server restarts, AND BFCache entry.
// Schedule a reconnect (with back-off in production).
setTimeout(connect, 1000);
});
}
// Initial connection.
connect();
// When the page is restored from BFCache, re-establish if close
// handler hasn't already scheduled a reconnect.
window.addEventListener("pageshow", (event) => {
if (event.persisted && ws.readyState !== WebSocket.OPEN) {
connect();
}
});
Check BFCache eligibility in DevTools
// Chrome DevTools: Application → Back/Forward Cache → Test.
// A page with an open WebSocket now shows as BFCache-eligible.
// Previously it listed "WebSocket" in the blocking-reasons list.
compatibility notes
| Apps that reconnect on close | No action needed. BFCache now works. Users get faster back/forward navigation. |
|---|---|
| Apps that assume connection is always live | Will stall after BFCache restore. Add a pageshow + readyState check. |
Apps that use WebSocketStream |
Same behavior — streams are closed on BFCache entry. |
| Server-side sessions tied to socket lifetime | A close from BFCache entry looks identical to a normal close. Server-side timeout/reconnect logic should handle it cleanly. |
browser support
| Chrome | 149 — WebSocket connections no longer block BFCache |
|---|---|
| Edge | 149 (Chromium) |
| Firefox | BFCache supported; WebSocket behaviour may differ — check MDN BFCache docs |
| Safari | BFCache supported; WebSocket behaviour may differ — check WebKit release notes |