Skip to content

Cross-Tab & Files

Coordinating across tabs and persisting files

Section titled “Coordinating across tabs and persisting files”

Modern web apps often run in multiple browser tabs simultaneously — a user may have the same dashboard open in two windows. When one tab updates data, how does the other find out? When the app needs to write a large file, how does it avoid clobbering work in a concurrent tab? This module answers both questions.

The browser gives you four complementary APIs:

  • BroadcastChannel — publish/subscribe messaging across every tab (and worker) on the same origin.
  • storage event — fired on other tabs when localStorage is written; the original notification mechanism before BroadcastChannel.
  • Web Locks — a mutual-exclusion primitive that serialises access to a named resource, preventing race conditions.
  • File System Access / OPFS — read and write real files (or a private origin sandbox) with a streaming, async API.
flowchart LR
  subgraph Origin["Same origin (scheme + host + port)"]
    TabA["Tab A\n(writer)"] -->|postMessage| BC["BroadcastChannel\n'app-updates'"]
    BC -->|onmessage| TabB["Tab B\n(listener)"]
    BC -->|onmessage| TabC["Tab C\n(listener)"]
    TabA -->|setItem| LS[(localStorage)]
    LS -->|storage event| TabB
    LS -->|storage event| TabC
  end
BroadcastChannel and the storage event both deliver messages to every other tab on the same origin
LessonWhat you will learn
This pageThe four cross-tab and file APIs and when to reach for each one
broadcastchannelnew BroadcastChannel(name), postMessage, onmessage, close; vs the storage event
web-locksnavigator.locks.request, exclusive vs shared mode, ifAvailable, locks.query()
cross-tab-stateCombining BroadcastChannel + localStorage/IndexedDB for shared state; leader election with Web Locks
file-system-access-opfsshowOpenFilePicker / showSaveFilePicker (user gesture required) and OPFS navigator.storage.getDirectory()
APIDeliveryRequires gestureWorks in workersPersistent
BroadcastChannelother tabsnoyesno
storage eventother tabsnonono
Web Lockssame tabnoyesno
File System Accessyes (picker)noyes
OPFSnoyesyes

The snippet below creates a BroadcastChannel and immediately posts and receives a message in the same page. In a real app the sender and receiver are in separate tabs.

Browser Storage
Which API delivers messages to every other tab open on the same origin without requiring a user gesture?
The `storage` event fires when localStorage is written. Which tab receives it?
Which API requires a user gesture (like a button click) before it can show a file picker?