Make live state reliable

Coordinate browser tabs

Use BroadcastChannel to share same-origin updates or leadership without opening redundant live connections.

Three tabs open on the status board means three live server connections unless you plan for it. That wastes file descriptors and makes reconnect storms worse.

BroadcastChannel lets same-origin tabs talk locally. One tab can own the server connection and relay updates to the others. See The BroadcastChannel API for the basics.

Leader election sketch

const channel = new BroadcastChannel('status-board')
const tabId = crypto.randomUUID()
let leader = false

channel.postMessage({ type: 'hello', tabId })

channel.onmessage = (event) => {
  if (event.data.type === 'event.incident.updated') {
    applyIncidentUpdate(event.data.payload)
  }
}

function becomeLeader() {
  leader = true
  source = new EventSource('/events')
  source.addEventListener('incident.updated', (event) => {
    const payload = JSON.parse(event.data)
    applyIncidentUpdate(payload)
    channel.postMessage({ type: 'event.incident.updated', payload })
  })
}

Only the leader opens EventSource. Followers update from channel.onmessage.

Handover when the leader closes

Leaders crash. Close the leader tab on purpose:

window.addEventListener('pagehide', () => {
  if (leader) {
    channel.postMessage({ type: 'leader.gone', tabId })
  }
})

Remaining tabs run a short timer, then one promotes itself and reconnects. Followers must tolerate duplicate events because handover overlaps with the old stream for a moment.

Limits to remember

BroadcastChannel is browser-local. It does not reach other devices, workers on other origins, or tabs after every copy closed unless you persisted state elsewhere.

Keep an independent snapshot recovery path. If every tab dies, the next visit still loads GET /api/incidents.

Open three tabs, close the leader, and verify another tab reconnects without losing the current incident list.

Duplicate tolerance during handover

For two seconds both the old and new leader may deliver the same evt_88. Followers should run the same duplicate filter from the previous lesson instead of double-applying UI side effects like toast notifications.

I still open a snapshot when any tab loads cold. Leadership optimization is about server load, not about skipping the HTTP source of truth on first paint.

Try this on your own project: elect one leader per origin, relay events over BroadcastChannel, and fall back to snapshot when no leader answers within five seconds.

Lesson completed