BroadcastChannel — Cross-Tab Messaging
debt(d7/e3/b3/t5)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate no automated detection ('automated: no'), and the code_pattern is simply 'BroadcastChannel'. Misuses such as forgetting channel.close(), expecting self-receipt, or cross-origin confusion are silent at runtime — no linter or compiler flags them. Testing or manual review is required to catch these.
Closest to 'simple parameterised fix' (e3). The quick_fix indicates adding close() in cleanup and adjusting message-receipt expectations — small, localised changes within the component that uses BroadcastChannel. No cross-cutting refactor is needed; fixes are confined to the relevant tab/page context.
Closest to 'localised tax' (b3). BroadcastChannel usage is scoped to the web context and typically confined to specific feature areas (auth state, theme, cart). It does not impose a structural weight on the rest of the codebase — only the components using it pay the cost of managing channel lifecycle.
Closest to 'notable trap' (t5). The misconception field explicitly states that developers expect the sender tab to receive its own messages — it doesn't. This is a documented gotcha that most developers hit when first using the API, contradicting the intuition that 'broadcast' means 'everyone including me'. Not catastrophic, but a clear and common surprise.
TL;DR
Explanation
BroadcastChannel(name) creates a named channel. Messages posted with channel.postMessage(data) are received by all other pages on the same origin subscribed to the same channel name — not the sender itself. Data is structured-cloned (supports objects, ArrayBuffers, not functions). Use cases: tab synchronisation (logout across all tabs), shared state updates, cross-tab notifications. Close with channel.close() when done. Compared to Service Worker messaging: simpler, no SW required. Compared to localStorage events: more reliable, supports rich data types.
Common Misconception
Why It Matters
Common Mistakes
- Not calling channel.close() — channels persist as long as the page lives.
- Expecting the sender to receive its own messages — it doesn't.
- Using BroadcastChannel across different origins — blocked by same-origin policy.
Code Examples
// localStorage events — limited to string values:
localStorage.setItem('logout', Date.now());
window.addEventListener('storage', e => {
if (e.key === 'logout') logout();
});
const channel = new BroadcastChannel('auth');
// Send logout to all other tabs:
channel.postMessage({ type: 'logout', timestamp: Date.now() });
// Receive:
channel.onmessage = ({ data }) => {
if (data.type === 'logout') logout();
};
// Cleanup:
channel.close();