Most web devs sync browser tabs using localStorage
or BroadcastChannel
. But what if you need instant, high-frequency data sharing between tabs — like a multiplayer editor or live data dashboard?
Turns out, you can use SharedArrayBuffer
+ Atomics
to achieve true shared memory between tabs — like low-level multi-threading in JavaScript. It’s crazy fast and doesn't need a server.
Let’s build a blazing-fast, zero-latency cross-tab bus using shared memory.
Step 1: Enable Cross-Origin Isolation (Required)
For security, SharedArrayBuffer
is only available in cross-origin isolated contexts. You’ll need to serve your site with special headers:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
If you're using Vite, add this to vite.config.ts
:
server: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp"
}
}
Now SharedArrayBuffer
is enabled.
Step 2: Create Shared Memory Buffer
Each tab will access the same memory buffer using postMessage
with transferable ownership.
const sharedBuffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 1024);
const sharedArray = new Int32Array(sharedBuffer);
You can use this like a raw memory segment. But how do other tabs get access to the same buffer?
Step 3: Share Memory Between Tabs via window.open
Unfortunately, different tabs can’t share memory automatically — but you can pass the buffer using postMessage
and the window.open()
reference.
Tab A (main window):
const child = window.open("/child.html");
child.addEventListener("load", () => {
child.postMessage(sharedBuffer, "*", [sharedBuffer]);
});
Tab B (child window):
window.addEventListener("message", (e) => {
const shared = new Int32Array(e.data);
startWatching(shared);
});
You now have shared memory between tabs.
Step 4: Use Atomics to Sync Writes
Use Atomics
to coordinate read/write access and notify changes:
// Writer (in Tab A)
Atomics.store(sharedArray, 0, Date.now()); // write a timestamp
Atomics.notify(sharedArray, 0); // notify any listener
// Reader (in Tab B)
function startWatching(shared) {
function waitLoop() {
Atomics.wait(shared, 0, 0); // wait until value changes
const timestamp = Atomics.load(shared, 0);
console.log("New data received:", new Date(timestamp));
waitLoop();
}
waitLoop();
}
This loop blocks (in a worker or idle time) until a change is written. It's fast — and zero-polling.
Step 5: Add a Messaging Protocol
You can extend the buffer to hold structured messages — like IDs, types, or payloads.
// Convention:
// Index 0: change flag
// Index 1: message type
// Index 2..: payload
// Writer
Atomics.store(sharedArray, 1, 42); // message type
Atomics.store(sharedArray, 2, 1234); // payload
Atomics.store(sharedArray, 0, 1); // signal change
Atomics.notify(sharedArray, 0);
You now have a structured event bus shared between browser tabs — no server or DB required.
✅ Pros:
- ⚡ Blazing-fast memory sharing across tabs
- 🧠 Enables real-time collaboration or analytics dashboards
- 📴 Works completely offline
- 🔍 No need for localStorage, IndexedDB, or BroadcastChannel
- 🧵 True concurrent memory management via Atomics
⚠️ Cons:
- 🚫 Requires cross-origin isolation (not supported everywhere)
- 🔐 Can’t share memory unless one tab opened the other
- 🧪 Debugging shared memory is non-trivial
- 🧠 Only supports low-level numeric types (use structured memory carefully)
Summary
With SharedArrayBuffer
and Atomics
, the browser can now act like a mini operating system — complete with shared memory concurrency, manual locking, and realtime updates between tabs. This technique opens doors to collaborative apps, multiplayer UIs, and in-browser data engines — with zero server roundtrips.
It’s underused, extremely powerful, and just waiting to be applied to your next high-performance web tool.
Want to Dive Deeper?
If you’re interested in taking your real-time cross-tab synchronization skills to the next level, check out my premium, in-depth guide on Gumroad. It covers advanced concepts, real-world use cases, optimizations, and much more, with plenty of hands-on code examples to help you build high-performance applications.
Click here to get the advanced guide on Gumroad!
The Gumroad guide includes:
- Advanced use cases for multiplayer games, real-time collaborative editors, and tab-to-tab remote control
- Performance optimization techniques for large-scale applications
- In-depth coverage of concurrency management and synchronization patterns
- Full, production-ready code examples you can adapt to your own projects
If you're looking to master SharedArrayBuffer and Atomics for real-time web apps, this guide is the ultimate resource for you!
If this was helpful, you can also support me here: Buy Me a Coffee ☕