Marcio Cunha

Global State Management in High-Frequency Web Applications with WebSockets and Shared Workers

Learn how to synchronize real-time data across multiple browser tabs using WebSockets and Shared Workers, reducing network overhead and eliminating state conflicts.

Marcio Cunha•5 min
Also available in:EspañolPortuguês
Summary
  • Multiple browser tabs competing for real-time connections create severe network bottlenecks and excessive battery consumption.
  • Using persistent WebSocket connections combined with Shared Workers centralizes data flow into a single master process on the client machine.
  • Communication between tabs and the central process occurs via the Broadcast Channel API, ensuring instant synchronization without duplicate sockets.
  • Local buffering strategies prevent critical packet loss if a tab is suddenly closed or reloaded mid-transaction.
  • The decentralized client-side architecture offloads the central server from redundant connections and drastically improves infrastructure scalability.

The Challenge of Real-Time Synchronization Across Multiple Tabs

When developing modern high-frequency web applications, such as financial dashboards, corporate chat systems, or infrastructure monitoring platforms, the volume of data received per second is staggering. In practice, this means hundreds of messages arrive in the browser via persistent connections known as WebSockets, keeping the interface updated without requiring manual page reloads. The problem arises when a user opens the same application across two or three different browser tabs. In this scenario, each tab attempts to open its own communication channel, duplicating network traffic, consuming more memory, and overloading the server with redundant requests.

To solve this operational bottleneck, we must rethink how global application state is distributed on the client machine. Instead of treating each tab in complete isolation, modern software engineering seeks to centralize incoming data feeds. This is where client-side concurrency comes into play, separating visual rendering tasks from heavy network communication tasks. The primary goal is to ensure the application runs smoothly, rapidly, and resource-efficiently on hardware, regardless of how many tabs remain open simultaneously.

The Role of WebSockets in Bidirectional Communication

WebSockets are communication protocols that allow continuous message exchange between the browser and the server over a single persistent TCP connection. In practice, unlike traditional HTTP where the client must repeatedly ask the server for updates, WebSockets open a direct, long-lived channel. This allows the server to push updates the exact moment they occur, which is essential for low-latency applications like stock market tickers or live sports scores.

However, the great advantage of WebSockets also introduces a complex architectural challenge when scaling to multiple instances within the same browser. If a user opens five tabs of a cryptocurrency dashboard, the WebSocket server must handle five distinct connections originating from the exact same person, transmitting the exact same payload. This wastes bandwidth, consumes server processing cycles to repeatedly serialize JSON, and can easily break backend connection limits. We need an intelligent bridge between the browser and the server.

Decentralizing with Shared Workers

Shared Workers are background scripts executed in the browser, isolated from the UI thread, that can be shared across multiple windows, tabs, or even iframes originating from the same origin. In practice, think of a Shared Worker as a miniature server process running directly on the user's machine, acting as a centralized manager. When the first tab opens, it initializes the Shared Worker. If the user opens other tabs subsequently, they connect to this same worker instead of spinning up brand-new network connections.

This architecture transforms the Shared Worker into the sole entity responsible for keeping the WebSocket connection alive with the external server. When a message arrives from the backend, the worker processes it and distributes it to all connected tabs in a coordinated manner. This drastically reduces RAM consumption and eliminates internet bandwidth waste, as the server now perceives only one connection per user, no matter how many tabs they decide to keep open concurrently.

Implementing Inter-Tab Communication with Broadcast Channel

For the Shared Worker to communicate effectively with the various user tabs, we rely on the Broadcast Channel API, a native mechanism in modern browsers enabling pub-sub communication across execution contexts of the same origin. In practice, this API acts like an internal radio station: the Shared Worker broadcasts a message on a specific channel, and all tabs tuned into that channel receive the information instantly to update their local states.

Practical implementation requires structured code resilient to network failures or sudden tab closures. Below is a simplified example demonstrating how to structure the logic inside a Shared Worker script to manage the connection and dispatch incoming events: To complement this implementation in production environments, see our related technical analyses on Global State Management in High-Frequency Web Applications with WebSocket Synchronization and State Management Architecture in High-Frequency Web Applications with Web Workers.

const connections = new Set();
const channel = new BroadcastChannel('app_state_channel');

let ws = new WebSocket('wss://api.example.com/stream');

ows.onmessage = (event) => {
  const data = JSON.parse(event.data);
  // Broadcast message to all listening tabs
  channel.postMessage(data);
};

onconnect = (e) => {
  const port = e.ports[0];
  connections.add(port);
  
  port.onmessage = (msgEvent) => {
    // Optional: handle messages from specific tabs
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify(msgEvent.data));
    }
  };
};

Handling State Conflicts and Fault Recovery

Managing real-time data across multiple contexts requires rigorous attention to message ordering and consistency. In practice, unstable mobile networks and Wi-Fi fluctuations can trigger temporary disconnections in the WebSocket managed by the Shared Worker. When connectivity drops, the worker must enter an exponential backoff reconnection routine, attempting to rejoin the server without flooding infrastructure with thousands of concurrent reconnection attempts per second.

Additionally, if a tab opens after a critical event has already occurred, it might drift out of sync with the rest of the application. To mitigate this, the Shared Worker retains a small snapshot of the last known global state in its internal memory. As soon as a new tab connects, it immediately receives this recent data snapshot, ensuring a seamless user experience devoid of blank screens or outdated info during browsing.

The architecture combining WebSockets and Shared Workers marks a major leap in high-frequency web application efficiency. By shifting connection management overhead to a centralized client-side process, we lighten backend infrastructure and safeguard end-user hardware resources from severe waste. While this design requires careful exception handling and inter-tab synchronization, the gains in performance, scalability, and UX heavily outweigh the engineering complexity.