Shared Workers vs Web Workers: What Is the Difference?
Learn the difference between SharedWorker and dedicated Web Workers, how ports and onconnect work, and when to use each.
Expected Interview Answer
A dedicated Web Worker is a background thread owned by a single browser tab or script, while a SharedWorker is a single background thread that multiple tabs, iframes, or windows from the same origin can connect to and communicate with simultaneously.
A dedicated worker is created with `new Worker(url)` and only the page that created it can post messages to it; when that page closes, the worker is torn down with it. A SharedWorker instead exposes a `port` object, and every connecting document calls `worker.port.start()` to open its own MessagePort onto the same underlying thread, so several tabs can share one long-lived computation, socket connection, or in-memory cache instead of duplicating it per tab. Because multiple contexts attach to a SharedWorker, its global scope has an `onconnect` handler rather than a single implicit message channel, and the browser keeps it alive as long as at least one connected document remains open. The tradeoff is debugging difficulty and support: SharedWorkers have no exposed thread inside most DevTools panels the way dedicated workers do, and they are unsupported in some mobile browsers, so many teams reach for a dedicated worker plus BroadcastChannel to coordinate tabs instead.
- Lets multiple tabs share one computation or connection instead of duplicating it
- Reduces memory and CPU by centralizing state across same-origin contexts
- Keeps a single WebSocket or IndexedDB writer coordinated across tabs
- Still runs off the main thread, so heavy work never blocks UI rendering
AI Mentor Explanation
A dedicated Web Worker is like a personal net bowler assigned to one batter alone, packing up the moment that batter leaves the nets. A SharedWorker is like a single bowling machine set up in the middle net that several batters from the same squad can queue up at and use together, each getting their own turn without a separate machine per batter. The machine keeps running as long as at least one batter is still using it, and it holds shared settings โ speed, line โ for everyone drawing from it. That one-thread-many-connected-users model is exactly what a SharedWorker gives multiple browser tabs.
Step-by-Step Explanation
Step 1
Create the SharedWorker
A tab calls `new SharedWorker(url)`, which either starts the worker or attaches to an already-running instance for that URL.
Step 2
Open a port
The tab calls `worker.port.start()` and registers `onmessage` to send and receive on its own MessagePort.
Step 3
Worker handles connections
Inside the worker, `onconnect` fires per connecting tab, each getting a `port` to communicate independently over the shared thread.
Step 4
Worker persists across tabs
The SharedWorker stays alive as long as at least one connected tab remains open, sharing state across all of them.
What Interviewer Expects
- Clear distinction between per-tab dedicated workers and cross-tab SharedWorkers
- Understanding of the port/onconnect model unique to SharedWorker
- Awareness of lifecycle differences (worker dies with its tab vs persists across tabs)
- Mention of debugging/support limitations that push teams toward alternatives
Common Mistakes
- Assuming a dedicated Worker can be reached from multiple tabs like a SharedWorker
- Forgetting to call `port.start()`, so messages silently never arrive
- Not knowing SharedWorker uses `onconnect` instead of a single top-level `onmessage`
- Ignoring browser support gaps (e.g., some mobile browsers lack SharedWorker)
Best Answer (HR Friendly)
โA regular Web Worker is a background thread that belongs to just one browser tab and disappears when that tab closes. A SharedWorker is one background thread that several tabs from the same site can all connect to and use together, which is handy for things like sharing a single live connection instead of opening one per tab.โ
Code Example
// Dedicated worker: only this tab can talk to it
const dedicated = new Worker('dedicated-worker.js')
dedicated.postMessage({ type: 'start' })
dedicated.onmessage = (e) => console.log('dedicated:', e.data)
// SharedWorker: every tab connects to the SAME thread
const shared = new SharedWorker('shared-worker.js')
shared.port.start()
shared.port.postMessage({ type: 'subscribe' })
shared.port.onmessage = (e) => console.log('shared:', e.data)
// Inside shared-worker.js
const connectedPorts = []
onconnect = (event) => {
const port = event.ports[0]
connectedPorts.push(port)
port.onmessage = () => {
connectedPorts.forEach((p) => p.postMessage({ type: 'update' }))
}
port.start()
}Follow-up Questions
- How would you coordinate tabs without SharedWorker support, using BroadcastChannel instead?
- How does SharedWorker lifecycle differ from a Service Worker?
- What debugging challenges come with inspecting a running SharedWorker?
- When would sharing a single WebSocket via SharedWorker be worth the complexity?
MCQ Practice
1. What is the key difference between a dedicated Worker and a SharedWorker?
SharedWorker exposes ports that multiple same-origin browsing contexts can connect to simultaneously.
2. What handler does a SharedWorker use to accept new tab connections?
SharedWorker fires `onconnect` for each new connecting document, providing a dedicated port.
3. When does a SharedWorker get terminated?
A SharedWorker persists as long as at least one connected document remains open.
Flash Cards
Who can talk to a dedicated Worker? โ Only the single tab/script that created it.
Who can talk to a SharedWorker? โ Multiple same-origin tabs, each via its own MessagePort.
SharedWorker entry handler? โ `onconnect`, fired once per connecting document.
Main SharedWorker limitation? โ Weaker DevTools support and inconsistent browser availability.