September 2, 2025
· 4 min readSharedWorker: The Hidden API for Multi-Tab Real-Time Apps
SharedWorker is a lesser-known browser API that enables multiple tabs, windows, or iframes of the same origin to share a single background worker. This post dives into use cases, performance benefits, comparisons with other workers, implementation details, and browser support.

SharedWorker: The Hidden API for Multi-Tab Real-Time Apps
Every modern web developer has faced the multi-tab problem: open your chat app or dashboard in five tabs, and suddenly you’ve got five duplicate WebSocket connections, five redundant API calls, and five times the server load.
That’s wasteful, especially in real-time apps where efficiency matters.
This is where SharedWorker, a quiet but powerful browser API, comes in. It allows multiple tabs (or even iframes) from the same origin to share a single background thread — perfect for managing shared connections and state.
Why SharedWorker?
Normally, each tab is isolated. If you create a WebSocket in one tab, another tab will open its own. SharedWorker breaks this pattern by acting like a singleton background service for all pages on the same origin.
This means:
- ✅ Only one WebSocket connection is opened
- ✅ Shared state can be stored once, not duplicated
- ✅ Tabs can communicate with each other via the worker
A chat app, notification system, or analytics dashboard becomes lighter and more scalable with this approach.
How SharedWorker Works
Let’s visualize the flow of a multi-tab WebSocket system using a SharedWorker:
👉 Multiple tabs → one worker → one WebSocket → shared messaging.
Use Cases
SharedWorker shines when:
-
Real-time communication
- Chat apps, notifications, collaborative editors
-
Shared connections
- One WebSocket, SSE, or WebRTC channel across all tabs
-
Cross-tab caching
- Fetch once, share results with every open tab
-
Multi-iframe apps
- Centralized event bus for embedded apps
-
Task coordination
- Distribute computations or state between contexts
💡 Tip: SharedWorker is especially useful in enterprise dashboards where users open multiple windows to monitor live data streams.
SharedWorker vs. Other Workers
Not all workers are created equal. Here’s how SharedWorker stacks up:
| Feature | DedicatedWorker | SharedWorker | ServiceWorker |
|---|---|---|---|
| Scope | One page/iframe only | All pages/frames of same origin | All pages under its registered scope |
| Lifetime | Ends with page | Ends when all clients close | Event-driven, persists in background |
| Communication | postMessage (one-to-one) |
MessagePort (multi-client) |
postMessage, fetch, push, sync |
| Access to DOM | ❌ | ❌ | ❌ |
| WebSocket support | Yes (per tab) | Yes (singleton) | ❌ |
| Network Control | Limited (per tab) | Shared across tabs | Full: intercept fetch, caching, offline |
| Best For | Heavy tab-specific computation | Multi-tab real-time coordination | Offline, caching, push notifications |
| Browser Support | Wide | Partial (~46% global) | Wide (modern browsers, HTTPS only) |
Architectural View
- DedicatedWorker: Each tab creates its own worker and manages its own resources.
- SharedWorker: All tabs share one worker → can centralize WebSocket or cache.
- ServiceWorker: One background service sits between all tabs and the network, ideal for caching and offline.
Implementation Example
In each tab (main.js):
const worker = new SharedWorker("shared.js");
worker.port.start();
worker.port.onmessage = (e) => {
console.log("From worker:", e.data);
};
worker.port.postMessage({ type: "chat", text: "Hello from Tab!" });SharedWorker script (shared.js):
let clients = [];
const socket = new WebSocket("wss://example.com/socket");
socket.addEventListener("message", (e) => {
clients.forEach(port => port.postMessage({ fromServer: e.data }));
});
onconnect = (event) => {
const port = event.ports[0];
clients.push(port);
port.start();
port.onmessage = (msg) => {
socket.send(JSON.stringify(msg.data));
};
};✅ Only one WebSocket is opened. ✅ All tabs share it seamlessly.
Enjoyed this post? Follow on LinkedIn for more engineering insights.
Performance & Security Considerations
Performance
- 🚀 Resource efficiency: One connection instead of many
- 🧠 Reduced memory/CPU load: Less duplication
- ⚡ Lower server load: Fewer sockets to maintain
Security
- 🔒 Same-origin only: All pages must match protocol, host, and port
- ❌ No DOM access: Worker is sandboxed
- 📜 Independent CSP: Worker script must include its own CSP headers
⚠️ Warning: Don’t rely on SharedWorker alone in production if Safari <16 or IE users are in your audience.
Browser Support
Browser support is limited:
- ✅ Chrome, Firefox, Edge (Chromium)
- ❌ Safari <16 (unsupported)
- ❌ IE (unsupported)
Global support: ~46%.
Fallbacks:
- BroadcastChannel API (~91% support)
localStorageevents (hacky but works)
Conclusion
SharedWorker is a scaling hack for multi-tab apps. It solves:
- Duplicate WebSocket connections
- Wasted bandwidth
- Fragmented state between tabs
Use it for real-time dashboards, chats, or collaborative tools — but be aware of Safari and legacy support issues. Always provide fallbacks like BroadcastChannel.
If you’re building a real-time browser app, SharedWorker could be the missing piece that makes your architecture leaner and smarter.
References
FAQ
What is a SharedWorker in JavaScript?
A SharedWorker is a special type of Web Worker that can be accessed by multiple browsing contexts (tabs, windows, iframes) from the same origin. It enables them to share state and resources like WebSockets.
When should I use SharedWorker over DedicatedWorker?
Use SharedWorker when you need shared state or connections across multiple tabs, like a single WebSocket for all tabs. Use DedicatedWorker when you need to offload computation within one tab.
Can ServiceWorkers replace SharedWorkers?
No. ServiceWorkers are designed for caching, offline support, and network interception. They cannot maintain persistent connections like WebSockets. SharedWorkers are better for real-time multi-tab scenarios.
Does SharedWorker work in Safari?
Full support arrived only in Safari 16 (macOS 13, iOS 16). Older Safari versions do not support SharedWorker, which limits its production viability.
How does SharedWorker improve performance?
It reduces duplicate work by centralizing shared resources. For example, instead of each tab opening its own WebSocket, one SharedWorker manages a single connection, reducing memory, CPU, and server load.
What are some fallbacks if SharedWorker isn’t supported?
Use the BroadcastChannel API for inter-tab messaging, or rely on localStorage events. These do not provide shared connections but can coordinate state between tabs.
Can SharedWorkers access the DOM?
No. Like other workers, SharedWorkers run in isolated threads without direct DOM access. Communication is only possible via message passing.