DEV Community

Cover image for Real-Time Cross-Tab Sync with SharedArrayBuffer and Atomics (No Server, No BroadcastChannel)
HexShift
HexShift

Posted on

Real-Time Cross-Tab Sync with SharedArrayBuffer and Atomics (No Server, No BroadcastChannel)

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

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

Postmark Image

"Please fix this..."

Focus on creating stellar experiences without email headaches. Postmark's reliable API and detailed analytics make your transactional emails as polished as your product.

Start free