Fact-checked by Grok 2 weeks ago

Web worker

A Web Worker is a feature defined in the Living Standard that enables web applications to run scripts in isolated background threads, separate from the main execution thread responsible for rendering the , thereby preventing script execution from blocking or freezing the page during intensive computations. Introduced as part of the in 2007 and achieving broad browser support by 2012, Web Workers were developed to address the single-threaded nature of in browsers, allowing developers to offload CPU-intensive tasks such as , image manipulation, or complex calculations without compromising . Web Workers operate within a restricted , lacking direct to the (DOM), window object methods, or parent page scripts to ensure security and isolation, but they support standard execution, network requests via APIs like fetch() or XMLHttpRequest, and communication with the main thread through a message-passing system using postMessage() and event handlers. There are three primary types: dedicated workers, which are tied exclusively to the script that creates them and terminate when that script unloads; shared workers, which can be accessed by multiple scripts from the same and persist across page navigations; and service workers, a specialized variant that acts as a between web apps, the , and the network for tasks like offline caching and push notifications. This API is particularly valuable for modern , where responsive performance is critical, but it comes with considerations such as higher usage and startup costs, making it suitable for long-running, resource-heavy operations rather than lightweight or short-lived tasks. Workers are created using the Worker constructor, passing a to a file, and can be terminated manually to manage resources efficiently.

Introduction

Definition and Purpose

Web Workers are a that enables web applications to run scripts in background threads isolated from the main execution thread, allowing for parallel processing without interfering with the user interface. This mechanism addresses the inherent single-threaded nature of in browsers, where computationally intensive operations would otherwise block the main thread and cause the UI to freeze. The primary purpose of Web Workers is to offload resource-heavy tasks, such as , image manipulation, or complex calculations, to these background threads, thereby maintaining application responsiveness during long-running operations. For instance, tasks like generating prime numbers or resizing large images can be delegated to a worker, preventing delays in user interactions like scrolling or clicking. This approach enhances by ensuring smooth performance in dynamic web environments, particularly for single-page applications handling real-time data. Key benefits include improved overall responsiveness and the introduction of multi-threading capabilities to JavaScript's traditionally concurrent but single-threaded model, which supports more efficient handling of modern web workloads. At a high level, Web Workers operate within a distinct global context known as WorkerGlobalScope, which provides a sandboxed environment without direct access to the main thread's (DOM) or object, promoting security and isolation. Interaction between the main thread and workers occurs primarily through , enabling asynchronous data exchange while preserving thread separation.

History and Development

The development of Web Workers originated in the late 2000s as part of broader initiatives aimed at overcoming JavaScript's single-threaded model, which often led to unresponsive user interfaces during computationally intensive tasks. This need was particularly acute with the proliferation of AJAX-driven web applications and the growing emphasis on mobile web performance, where blocking the main thread could degrade user experience on resource-constrained devices. The released the initial draft specification for Web Workers on March 27, 2009, defining an API for spawning background scripts to run independently of the main page thread. Standardization progressed through the WHATWG's living standard process, with early browser implementations accelerating adoption. Firefox 3.5 introduced support for Web Workers on June 30, 2009, followed by Safari 4 on June 8, 2009, Chrome 4 on January 25, 2010, and 10.6 in September 2010. The (W3C) advanced the specification to Candidate Recommendation status on May 1, 2012, marking a key milestone in , though it has since evolved continuously under the WHATWG's HTML Living Standard without reaching full W3C Recommendation due to the dynamic nature of web technologies. Subsequent enhancements expanded Web Workers' capabilities while addressing performance and security challenges. Shared Workers, allowing multiple scripts to connect to a single worker instance for resource sharing, were included in the original 2009 draft and saw initial implementations in 5 (September 2010) and 29 (April 2014). Transferable objects, introduced in the specification around 2011, enabled zero-copy data transfer between threads via structured clone with an optional transfer array, significantly reducing overhead for large payloads like ArrayBuffers. In 2017, SharedArrayBuffer integration allowed atomic shared memory access across workers to support multithreading in , but following the vulnerability disclosures in early 2018, browsers disabled it by default, requiring sites to implement cross-origin isolation mitigations for re-enablement.

Core Concepts

Threading Model

Web Workers enable multi-threaded execution in web applications by allowing code to run in background threads separate from the main thread, which remains single-threaded for handling and rendering tasks. The main execution thread processes synchronously in a single context, potentially blocking the UI during intensive computations, whereas Workers create parallel execution contexts to offload such tasks without interfering with the primary thread. Workers operate in , each running in its own background with a dedicated , , and , ensuring no shared mutable state with the main or other Workers by default. This separation prevents direct access to the DOM, the window object, or parent.document, but provides limited through objects like WorkerNavigator (for navigation-related properties) and WorkerLocation (for information). The in a Worker functions asynchronously, queuing and processing tasks such as script execution and message handling in a manner similar to the main thread's , but without any rendering or update responsibilities. The lifecycle of a Web Worker begins with via the Worker constructor, which fetches and executes the associated script in the background , triggering event-driven execution through handlers like onmessage for incoming data and onerror for script errors. Termination can occur externally via the terminate() method called on the Worker object from the main , which immediately halts the without allowing completion of ongoing operations, or internally via the close() method invoked within the Worker script, which discards pending tasks in its .

Communication Mechanisms

Communication between the main thread and Web Workers occurs exclusively through message passing, necessitated by the threading model's isolation that prevents direct shared memory access. The primary API for inter-thread communication consists of the postMessage() method for sending messages and the onmessage event handler for receiving them. The postMessage() method, available on both the Worker object in the main thread and the worker's global scope, accepts a message payload—typically a JavaScript object—and serializes it before transmission. The onmessage event fires upon receipt of a message, allowing the receiving context to process the incoming data asynchronously. Messages undergo via the structured clone , which creates a deep copy of the transmitted data to ensure . This supports cloning of primitive values, arrays, objects (including cyclical references), and certain other types like Date and RegExp instances, but excludes functions, DOM nodes, and other non-serializable elements. However, certain objects such as ArrayBuffers and MessagePorts can have their ownership transferred to the receiver instead of cloned, avoiding the copy overhead, by providing a transfer list as the second argument to postMessage(). As a result, the receiver obtains an independent copy for cloned data or direct access for transferred objects, preventing unintended mutations across threads. Error propagation from a Worker to the main thread is handled through the onerror event, which captures uncaught runtime exceptions or script loading failures within the Worker. This event provides details such as the error message, filename, and line number, enabling the main thread to respond appropriately without terminating the Worker. Messages are encapsulated in MessageEvent objects, which expose key properties including data (the deserialized payload), origin (the sender's origin as a string), and ports (an array of MessagePort objects for establishing bidirectional channels if ports are transferred). These properties provide contextual metadata essential for secure and targeted message handling.

Types of Workers

Dedicated Workers

Dedicated workers represent a type of Web Worker that is exclusively bound to the script which instantiates it, establishing a relationship between the worker and its creating . This binding ensures that the worker operates in from other scripts, running in a background to handle tasks without blocking the main thread's responsiveness. Unlike other worker variants, dedicated workers are not designed for multi-context access, making them suitable for single-owner scenarios within a specific or tab. These workers are created using the Worker constructor, which can be called from the main thread or other workers, such as new Worker('worker.js'), where the argument specifies the of the script to execute in the worker's isolated . The worker's lifetime is tied to its parent ; it automatically terminates when the creating unloads, or it can be manually terminated via the terminate() method on the Worker object, which discards any pending tasks and aborts the script execution. This automatic cleanup helps manage resources efficiently in single-use applications. Common use cases for dedicated workers include offloading computationally intensive operations from the main , such as large datasets or extensive payloads within a single tab or window, thereby preventing UI freezes during . For instance, in a handling user-uploaded files, a dedicated worker could process and validate the data in the background while the interface remains interactive. Communication with the main occurs via , but the worker's scope remains private, with no direct access to the DOM or other scripts, including those in iframes. The advantages of dedicated workers lie in their simpler isolation model, which reduces complexity for tasks that do not require sharing across multiple contexts, and their relatively lower overhead compared to more versatile worker types, as they avoid the synchronization mechanisms needed for multi-owner access. This makes them ideal for straightforward, task-specific processing where resource efficiency and ease of implementation are prioritized over broader reusability.

Shared Workers

Shared Workers represent a type of web worker that enables multiple browsing contexts—such as different tabs, windows, or iframes from the same —to access and interact with a single worker instance simultaneously. Unlike dedicated workers bound to a single context, Shared Workers maintain persistence across these contexts through a shared communication , facilitating coordinated background processing without duplicating resources. To create a Shared Worker, developers use the SharedWorker constructor, specifying the of the worker and an optional name for identification. The name allows multiple Shared Workers with the same to be distinguished, enabling scripts to connect to the appropriate instance. For example:
javascript
const worker = new SharedWorker('/path/to/worker.js', { name: 'sharedCacheWorker' });
This constructor adheres to the , ensuring the is from the same as the creating context. Shared Workers are particularly suited for scenarios requiring resource sharing across multiple contexts, such as caching responses to reduce redundant calls in multi-tab applications or supporting real-time collaboration features where shared state, like user edits in a , must be synchronized without reloading. In these cases, the worker can maintain a central or broadcast updates via its , improving efficiency over individual worker instances per . Communication between the Shared Worker and connected contexts occurs exclusively through MessagePort objects, which support structured data transfer via postMessage(). Upon instantiation, the worker exposes a port property for direct use by the creating ; additional connections from other contexts trigger a connect event in the worker , providing access to new ports. For instance, in the main :
javascript
worker.port.start();  // Opens the port for bidirectional communication
worker.port.postMessage({ action: 'fetchData', url: '/api/data' });
worker.port.onmessage = ([event](/page/Event)) => {
  console.log('Received:', event.data);
};
In the worker script (worker.js):
javascript
self.onconnect = (event) => {
  const port = event.ports[0];
  port.onmessage = (event) => {
    // Process message and respond
    port.postMessage({ result: 'processed data' });
  };
};
This port-based model ensures isolation while allowing , similar to the general worker threading model. The lifecycle of a Shared Worker is tied to its : it remains active as long as at least one browsing context holds a reference to it and the is open. If all close, the worker enters an inactive and terminates automatically after an implementation-defined timeout, often around 5 seconds, to conserve resources. This persistence contrasts with dedicated workers, which terminate when their single owner unloads. Browsers enforce quotas on Shared Workers to manage resource usage, limiting the number of concurrent instances per origin; these limits vary by user agent and are not strictly specified in the standard but help prevent abuse.

Implementation

Creating and Using Workers

Web Workers are instantiated using the Worker() constructor, which accepts the URL of a JavaScript file containing the worker script as its primary argument. This URL must resolve to a same-origin resource or a data URL, and the constructor asynchronously loads and executes the script in an isolated thread. An optional second argument is a WorkerOptions object that can specify { type: "module" } to treat the script as an ES module, { name: "worker-name" } to provide an identifying name primarily for debugging, and { credentials: "omit" | "same-origin" | "include" } to set the credentials mode for fetch requests (defaults: type "classic", credentials "same-origin"). The returned Worker object provides methods and events for interaction, with no explicit "load" event available, though the worker becomes active once the script initializes successfully. Errors during worker creation or script execution can be captured via the onerror event handler on the Worker object, which receives an ErrorEvent detailing the , , and . For instance, if the script URL is invalid, the error event fires to allow graceful handling in the main thread. A basic example demonstrates creating a worker to perform a simple , such as summing two numbers, using the API for communication between threads. In the main thread script:
javascript
const worker = new Worker('worker.js');
worker.onmessage = function(event) {
  console.log('Sum result:', event.data);
};
worker.onerror = function(error) {
  console.error('Worker error:', error.message);
};
worker.postMessage([5, 7]);  // Send array of numbers to sum
In the worker script (worker.js):
javascript
self.onmessage = function(event) {
  const numbers = event.data;
  const sum = numbers[0] + numbers[1];
  self.postMessage(sum);  // Send result back to main thread
};
This setup offloads the addition from the main thread, ensuring the UI remains responsive. Workers can be managed programmatically, with the terminate() method abruptly stopping execution, discarding any pending tasks, and closing communication ports. To reload or incorporate additional scripts within a running worker, the global importScripts() function synchronously fetches and executes external files in the worker's scope. For example, calling importScripts('utils.js'); loads utility functions without restarting the worker. Upon navigation or unload, workers are automatically terminated by the , which sets a closing flag when the worker is no longer actively needed or permissible, preventing resource leaks across page loads. Common integration patterns include offloading resource-intensive loops to workers, such as iterative calculations like sequences, to avoid freezing the main . Workers can also manage timers using setTimeout() and setInterval(), or handle network requests via the Fetch API, isolating these operations from user interactions. For debugging, workers support standard console methods like console.log(), which route output to the browser's developer tools console, allowing inspection of worker-specific logs. Source maps for worker scripts enable setting and stepping through code in devtools, similar to main thread , by configuring the bundler or serving map files alongside the worker URL.

Data Transfer and Serialization

In Web Workers, data is communicated between the main thread and worker threads primarily through the postMessage() method, which serializes the data using the structured clone algorithm by default. This algorithm creates a deep copy of the data, allowing the sender to retain ownership while the receiver obtains an independent duplicate, supporting complex structures like objects, arrays, and certain primitives but excluding non-clonable items such as functions or DOM nodes. For performance-critical scenarios involving large datasets, developers can opt for transfers using transferable objects, which move resource ownership without duplication. Transferable objects, such as ArrayBuffer, ImageData, and MessagePort, enable efficient data passing by including them in the second argument of postMessage() as an array of items to . For instance, to an ArrayBuffer containing , the syntax is worker.postMessage(message, [buffer]), where the buffer's underlying memory is detached from the sender and attached to the receiver, resulting in a operation ideal for large payloads like a 1GB audio buffer. Upon , the original object in the sending context becomes neutered—its byteLength property returns 0 for ArrayBuffer, and any access attempt throws an exception, ensuring the resource is exclusively available in one context to prevent race conditions. This contrasts with standard structured cloning, where ownership is retained via copying, which is suitable for smaller or reusable data but incurs overhead for voluminous transfers, potentially doubling memory usage temporarily. MessagePort objects, created via MessageChannel, facilitate streaming or bidirectional communication channels that can themselves be transferred. A MessageChannel produces two entangled ports; one can be posted to a worker using postMessage(port, [port]), establishing a dedicated, full-duplex link for ongoing data exchange without repeated channel setup, useful for scenarios like progressive data loading or updates. These ports support the same postMessage() and can transfer further objects, enhancing in multi-worker architectures. Not all data types are transferable; for example, functions, certain DOM objects, and typed arrays like Uint8Array cannot be directly transferred and must undergo structured cloning, which serializes them but may lose methods or references. Attempting to transfer non-supported items results in a "DataCloneError" exception, requiring developers to extract transferable components, such as passing an ArrayBuffer instead of a view onto it. This limitation ensures but necessitates careful data preparation for optimal performance.

Limitations and Best Practices

Key Restrictions

Web Workers operate within a constrained environment designed to maintain from the main and ensure , preventing direct interference with the or unauthorized access to resources. This imposes several fundamental restrictions on what scripts running in workers can do, prioritizing safe, parallel execution without compromising the integrity of the hosting page. A primary restriction is the complete lack of access to the Document Object Model (DOM). Workers cannot manipulate HTML elements, apply styles, or handle events directly, as they operate in a separate global scope without the window or document objects available in the main thread. This design choice enforces thread isolation, requiring any UI updates to be communicated back to the main script via message passing. Workers also face limitations on available APIs and globals. They lack access to the parent object and certain browser APIs tied to the main context, such as those for direct interaction with the embedding page. While timers like setTimeout and setInterval are provided within the worker's WorkerGlobalScope, they are scoped to the worker thread and do not affect the main thread's execution. Other globals, such as localStorage or alert, are unavailable to prevent side effects outside the isolated environment. Regarding file and resource access, workers cannot load or read local files from the directly. Instead, they must rely on relative URLs for importing scripts and libraries, or use mechanisms like Blobs for dynamic code execution, all within the constraints of the worker's . This restriction ensures that workers cannot bypass sandboxing to access unauthorized local resources. All operations within workers must adhere to asynchronous patterns to avoid blocking the main thread. Synchronous I/O or computationally intensive tasks that could freeze the are not permitted in a way that impacts the primary execution context; instead, workers handle such workloads independently, with communication to the main thread occurring asynchronously via the postMessage API. This promotes non-blocking behavior across the application. From a security perspective, the strictly applies to workers, confining them to resources from the same origin as the parent page. Cross-origin script loading or resource access is prohibited without proper (CORS) headers, mitigating risks like unauthorized or injection attacks in the isolated thread.

Performance and Security Considerations

Web Workers introduce performance overhead primarily through their startup time and data communication mechanisms. Creating a Worker typically incurs a of around 40 milliseconds on mid-range devices, though this can vary by browser and hardware; for instance, benchmarks on in 2015 showed stable instantiation times in this range. Message passing via postMessage() adds further costs due to structured cloning , which copies data rather than sharing it, leading to noticeable delays for large payloads—up to several milliseconds per round trip for small messages, scaling with size. Developers should tasks exceeding approximately 16 milliseconds, as per performance guidelines, to determine if offloading to a Worker justifies the overhead, since shorter operations may not benefit after accounting for setup and communication. To optimize performance, best practices emphasize reducing communication frequency and volume: minimize the number of messages exchanged between the main thread and Worker to avoid repeated , and batch data where possible. For binary or large structured data like ArrayBuffer instances, employ transferable objects to enable zero-copy transfers, which eliminate cloning overhead and improve efficiency for intensive computations. Always terminate idle Workers using the terminate() method to free resources promptly, preventing unnecessary persistence; for older browsers lacking full support, implement feature detection or polyfills to gracefully fallback to main-thread execution. These strategies can significantly mitigate the costs of Worker usage, particularly in scenarios involving frequent data exchange. Security considerations for Web Workers center on isolating potentially untrusted scripts, as Workers execute in a separate context from the main thread but inherit the . Loading scripts from untrusted sources risks executing malicious code, including dynamic evaluation via eval(), which can introduce vulnerabilities like if user-supplied data is processed without validation. To mitigate this, apply (CSP) headers specifically to Worker scripts using the worker-src directive, which restricts loading to trusted origins and blocks inline or eval-based execution; without explicit CSP, Workers may bypass the parent's policy when loaded via data or blob URLs. Sandboxing through strict CSP ensures that even same-origin Workers cannot access sensitive APIs, reducing risks. Effective is crucial to avoid leaks in Web Worker implementations, as unterminated Workers can retain allocated objects indefinitely, leading to gradual consumption of browser resources. Regularly invoke terminate() on completed or idle Workers to trigger garbage collection and release memory; failure to do so may result in persistent allocations, especially in long-running applications with multiple Workers. Monitor usage via the Performance API's measureUserAgentSpecificMemory() method, which provides aggregated metrics to detect leaks and regressions in production environments. Combining this with transferable objects further aids memory efficiency by avoiding duplicated buffers during data transfer. As of 2025, Web Workers benefit from enhanced integration with (Wasm), enabling near-native performance for tasks like AI inference by compiling Wasm modules directly within Workers, offloading heavy computations without main-thread interference. Post-Spectre mitigations, including reduced timer resolution in browsers like , introduce some performance overhead in affected workloads—but Workers' isolated execution model limits broader impacts compared to scenarios, preserving overall responsiveness.

Browser Support

Compatibility Overview

Web Workers enjoy near-universal support across modern web browsers as of 2025, with full implementation in all major and engines dating back to the early . has supported Web Workers since version 4 (2009), since 3.5 (2009), since 4 (2009), since 12 (2015), and since 11.5 (2011), ensuring compliance in all post-2010 versions. This broad compatibility covers over 95% of global browser usage, making Web Workers a reliable feature for multithreading in web applications without significant fallback requirements. On mobile platforms, support is equally robust, with Safari implementing Web Workers from version 5 (2010) and Browser from 4.4 (2013), alongside full coverage in for since version 4. These versions align with the dominance of modern mobile browsers, achieving approximately 95% global mobile coverage and eliminating the need for polyfills in contemporary development. Advanced features like transferable objects, which enable data transfer for improved , have been available since 2011 in 17 and similarly early versions in other browsers, with full cross-browser support today. Shared Workers, a variant for cross-tab communication, follow suit with support in 4+, 29+ (2014), and recent (79+) and (16+) versions, though global coverage is approximately 51% due to historical and ongoing gaps in some environments. Developers can detect Web Worker availability using direct feature tests, such as try-catch blocks around the Worker constructor, or via .hardwareConcurrency to gauge available threads, supported in 37+, 48+, 10.1 and 15.4+, and 15+. Given the technology's maturity, no active polyfills are necessary for browser environments, as legacy non-supporting browsers represent negligible .

Historical Adoption

Web Workers emerged as a key feature in the specification, with early browser implementations beginning in 2009. version 3.5, released in June 2009, was among the first to provide full support, enabling developers to offload execution to background threads. Similarly, version 4, launched later that year, introduced comprehensive compatibility, marking these as the initial adopters that facilitated experimentation with multithreading in web applications. Safari followed with support starting in version 4 in 2009, though initial implementation was partial, limiting certain advanced features until version 5 in 2010 provided fuller capabilities. lagged behind, adding support in version 11.5 in 2011, while trailed significantly, not incorporating Web Workers until version 10, released in October 2012. This uneven rollout, particularly Internet Explorer's delay, restricted widespread adoption in the early years, as developers targeted cross-browser compatibility for enterprise and broad-audience sites. Prior to 2010, the fragmented support landscape prompted the creation of libraries to manage worker instances in supported browsers, such as WorkerPool, which allowed pooling of workers to optimize usage and simulate multithreading more efficiently despite limitations. Even after universal support emerged around 2015, Web Workers remained underutilized due to their inherent complexity, including restrictions on direct DOM access and data serialization overhead, which deterred casual integration into simpler web projects. Adoption accelerated with the rise of single-page applications (SPAs) built on frameworks like and , where offloading computationally intensive tasks—such as or image manipulation—became essential for maintaining responsiveness. Usage metrics from the HTTP Archive indicate steady growth; by 2022, approximately 12% of analyzed desktop and mobile pages employed Web Workers, rising to 30% on mobile by 2024, reflecting integration in performance-critical modern web apps. As of 2025, Web Workers enjoy near-universal browser compatibility, with negligible unsupported versions among active user bases, shifting developer focus toward optimization techniques like and integration with for enhanced efficiency.

Service Workers

Service workers are a specialized type of web worker designed to act as proxy scripts that intercept and manage network requests between a and the network, contrasting with the computational focus of standard web workers. Unlike web workers, which primarily offload CPU-intensive tasks from the main thread to prevent UI blocking, service workers enable background processing for network-related operations, such as caching resources for offline access. Key differences between service workers and web workers include their event-driven nature and lifecycle management. Service workers respond to specific events like fetch (for network requests), (for notifications), and (for background ), operating independently of any specific or . They feature a persistent lifecycle that allows them to remain active even when no pages are open, provided the browser deems them necessary, whereas web workers are typically tied to the lifespan of the page or thread that spawns them. Additionally, while both lack direct access to the DOM to ensure isolation, service workers gain access to the Fetch for intercepting requests and the Cache for , enabling proxy-like behavior without the computational emphasis of web workers. Service workers are particularly suited for use cases involving offline functionality and enhanced user engagement in web applications. They power offline apps by caching assets and responses, allowing content to load without network connectivity, and support push notifications to deliver timely updates even when the app is not active. In scenarios requiring heavy computation alongside network proxying, a service worker can spawn dedicated to handle processing tasks, combining their respective strengths for efficient background operations. In terms of API overlap, both service workers and web workers utilize the postMessage method for inter-thread communication, facilitating data exchange between the main thread and the worker context. However, service workers extend this foundation with specialized , such as the Cache API for managing request-response pairs and event handlers like respondWith for customizing fetch responses, which are absent in standard web workers. Service workers were first outlined in a W3C Working Draft in 2015, with full browser support achieved across major engines by 2017— and in 2016, in 2017, and in 2018. They have become essential for progressive web apps (PWAs), enabling core features like reliable offline experiences and background that elevate web applications to native-like reliability.

Shared Memory and WebAssembly

SharedArrayBuffer enables true between the main thread and Web Workers by allowing multiple execution contexts to access and modify the same underlying memory buffer without copying data. Unlike ArrayBuffer, which is transferable but not shareable, SharedArrayBuffer propagates changes across threads in real-time, facilitating efficient multi-threaded computations. This feature was introduced in 2017 but disabled in early 2018 due to vulnerabilities exposed by and Meltdown attacks, which could allow cross-origin data leakage; it was re-enabled in 2020 after browsers implemented cross-origin isolation mitigations. To use SharedArrayBuffer, developers must establish cross-origin isolation on the document by setting specific HTTP response headers: Cross-Origin-Opener-Policy (COOP) to "same-origin" to prevent sharing browsing context groups with cross-origin documents, and Cross-Origin-Embedder-Policy (COEP) to "require-corp" or "credentialless" to restrict embedding of cross-origin resources without explicit permissions. Once isolated, verified via the .crossOriginIsolated property, SharedArrayBuffer instances can be created and posted to workers using postMessage, as in the following example:
javascript
// Main thread
const sab = new SharedArrayBuffer(1024);
const worker = new Worker('worker.js');
worker.postMessage(sab);  // Share the buffer reference without copying data

// Worker thread
self.onmessage = (e) => {
  const sab = e.data;
  const view = new Int32Array(sab);
  // Modify shared memory
};
This setup supports high-performance scenarios where data transfer costs would otherwise dominate, such as numerical simulations or image processing. The Atomics API complements SharedArrayBuffer by providing low-level synchronization primitives to manage concurrent access and avoid race conditions in shared memory environments. Key methods include Atomics.wait() and Atomics.notify() for thread coordination, modeled after futexes, which allow a thread to block until a shared value changes; arithmetic operations like Atomics.add() and Atomics.sub() for atomic updates; and data access methods such as Atomics.load(), Atomics.store(), and Atomics.compareExchange() to ensure consistent reads and writes across threads. These operations are essential in Web Workers, where non-atomic access could lead to unpredictable behavior, and they guarantee hardware-level atomicity where supported via Atomics.isLockFree(). For instance, a -consumer pattern might use Atomics.wait() in the consumer worker to pause until the producer signals via Atomics.notify() after updating a shared flag. WebAssembly threads extend this capability by allowing WebAssembly modules to execute in multi-threaded Workers, leveraging SharedArrayBuffer for shared linear memory and Atomics for . The Threads proposal, implemented in major browsers since 2020 (Chrome 74, Firefox 79, Safari 14.1), enables compiling multi-threaded C/C++ or code to WebAssembly with the --enable-threads flag during compilation, then instantiating shared memories via new WebAssembly.Memory({initial: 1, maximum: 10, shared: true}). This is particularly useful for compute-intensive tasks like game engines (e.g., physics simulations) or inference, where WebAssembly's near-native performance combines with Worker isolation to offload the main thread without blocking UI responsiveness. As an alternative to full data transfer via postMessage, SharedArrayBuffer reduces overhead in these scenarios, though transferables remain viable for non-shared data. In 2025, adoption of and threads in Web Workers has grown in performance-critical applications, driven by advancements in browser memory management and multi-threading optimizations that yield up to 10x speedups in scaled workloads. Use cases include in-browser inference with frameworks like WebLLM, where Workers host runtimes for parallel model execution, and real-time data processing in collaborative tools, supported by improved quotas and in modern devices.

References

  1. [1]
    HTML Standard
    Summary of each segment:
  2. [2]
    Use web workers to run JavaScript off the browser's main thread
    Dec 5, 2019 · In JavaScript, we can get roughly similar functionality from web workers, which have been around since 2007 and supported across all major ...Missing: introduction history<|control11|><|separator|>
  3. [3]
    Web Workers API - Web APIs - MDN Web Docs - Mozilla
    Apr 3, 2025 · Web Workers makes it possible to run a script operation in a background thread separate from the main execution thread of a web application.Using Web Workers · Functions and classes... · DedicatedWorkerGlobalScope
  4. [4]
  5. [5]
    JavaScript language overview - MDN Web Docs
    Oct 30, 2025 · JavaScript is single-threaded by nature. There's no paralleling; only concurrency. Asynchronous programming is powered by an event loop ...Data Types · Control Structures · Functions
  6. [6]
  7. [7]
  8. [8]
  9. [9]
    Worker() constructor - Web APIs - MDN Web Docs
    Jun 23, 2025 · The Worker() constructor creates a Worker object that executes the script at the specified URL. This script must obey the same-origin policy.
  10. [10]
    Web Workers - W3C
    This specification is the 01 May 2012 Candidate Recommendation. Comments for the 13 March 2012 Last Call Working Draft are tracked in the comment tracking ...
  11. [11]
    Transferable objects - Web APIs | MDN
    Sep 18, 2025 · Transferable objects are objects that own resources that can be transferred from one context to another, ensuring that the resources are only available in one ...Missing: definition | Show results with:definition
  12. [12]
    Using WebAssembly threads from C, C++ and Rust | Articles - web.dev
    Jul 12, 2021 · SharedArrayBuffer has a complicated history. It was initially shipped in several browsers mid-2017, but had to be disabled in the beginning of ...
  13. [13]
    Using Web Workers - Web APIs - MDN Web Docs
    Sep 11, 2025 · Web Workers are a simple means for web content to run scripts in background threads. The worker thread can perform tasks without interfering with the user ...Web Workers API · Transferring data to and from... · Embedded workers
  14. [14]
  15. [15]
  16. [16]
  17. [17]
    WorkerGlobalScope - Web APIs | MDN
    ### Summary: Event Loop and Context in Workers
  18. [18]
  19. [19]
  20. [20]
  21. [21]
    Worker: terminate() method - Web APIs - MDN Web Docs
    Jul 26, 2024 · The terminate() method of the Worker interface immediately terminates the Worker. This does not offer the worker an opportunity to finish its operations; it is ...Missing: lifecycle | Show results with:lifecycle
  22. [22]
    DedicatedWorkerGlobalScope: close() method - Web APIs | MDN
    ### Summary: How Workers Terminate Themselves
  23. [23]
  24. [24]
    Worker: postMessage() method - Web APIs | MDN
    ### Summary of Worker.postMessage()
  25. [25]
  26. [26]
  27. [27]
  28. [28]
    The structured clone algorithm - Web APIs | MDN
    Jun 29, 2025 · The structured clone algorithm copies complex JavaScript objects. It is used internally when invoking structuredClone(), to transfer data between Workers via ...Missing: definition | Show results with:definition<|control11|><|separator|>
  29. [29]
  30. [30]
    BroadcastChannel - Web APIs | MDN
    ### Summary: BroadcastChannel Usage in Shared Workers for Shared Communication
  31. [31]
  32. [32]
  33. [33]
  34. [34]
  35. [35]
    SharedWorker - Web APIs | MDN
    Dec 31, 2024 · footnote Nested workers support was introduced in Safari 15.5. footnote Script loading in nested workers was introduced in Safari 16.4. ...SharedWorker · SharedWorker: port property · SharedWorkerGlobalScope
  36. [36]
  37. [37]
  38. [38]
    SharedWorker() constructor - Web APIs - MDN Web Docs - Mozilla
    Aug 19, 2025 · footnote Nested workers support was introduced in Safari 15.5. footnote Script loading in nested workers was introduced in Safari 16.4. ...
  39. [39]
  40. [40]
  41. [41]
  42. [42]
  43. [43]
  44. [44]
  45. [45]
  46. [46]
  47. [47]
  48. [48]
  49. [49]
  50. [50]
  51. [51]
  52. [52]
  53. [53]
    MessagePort - Web APIs | MDN
    ### Summary of MessagePort Usage
  54. [54]
  55. [55]
  56. [56]
  57. [57]
  58. [58]
  59. [59]
  60. [60]
    How fast are web workers? - Mozilla Hacks - the Web developer blog
    Jul 2, 2015 · As expected, serializing, copying, and de-serializing data adds significant overhead to the message transmission. The bigger the message, the ...
  61. [61]
    When should you be using Web Workers? - surma.dev
    Jun 14, 2019 · Web Workers help your app run on a wider range of devices. Libraries like Comlink help you utilize workers without losing convenience and development velocity.Missing: guidelines | Show results with:guidelines
  62. [62]
    High-performance Web Worker messages | Read the Tea Leaves
    Feb 29, 2016 · In recent posts and talks, I've explored how Web Workers can vastly improve the responsiveness of a web application, by moving work off the UI ...
  63. [63]
  64. [64]
    Performance: measureUserAgentSpecificMemory() method
    Sep 14, 2025 · The measureUserAgentSpecificMemory() API aggregates memory usage data to help you find memory leaks. It can be used for memory regression ...
  65. [65]
    3W for In-Browser AI: WebLLM + WASM + WebWorkers - Mozilla.ai
    Aug 29, 2025 · ... WebAssembly compiles agent logic to near-native performance, and WebWorkers orchestrate both the model inference and agent execution off the ...How It Works · What This Enables · Enhancement Areas
  66. [66]
    Meltdown/Spectre | Blog - Chrome for Developers
    Feb 6, 2018 · As a mitigation, all major browsers have decreased the resolution of performance. now() to make it harder to mount the attacks.<|control11|><|separator|>
  67. [67]
    Web Workers | Can I use... Support tables for HTML5, CSS3, etc
    "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.
  68. [68]
    Transferable objects - Lightning fast | Blog - Chrome for Developers
    Dec 9, 2011 · With transferable objects, data is transferred from one context to another. It is zero-copy, which vastly improves the performance of sending data to a Worker.
  69. [69]
    Shared Web Workers | Can I use... Support tables for HTML5, CSS3 ...
    Method of allowing multiple scripts to communicate with a single web worker. Usage % of. all users, all tracked, tracked desktop, tracked mobile.Missing: introduction | Show results with:introduction
  70. [70]
    Navigator: hardwareConcurrency property - Web APIs | MDN
    Oct 16, 2024 · Browser compatibility ; Chrome – Full support. Chrome 37 ; Edge – Full support. Edge 15 ; Firefox – Full support. Firefox 48 ; Opera – Full support.
  71. [71]
    navigator.hardwareConcurrency | Can I use... Support ... - CanIUse
    "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.
  72. [72]
    How to think about Baseline and polyfills | Articles - web.dev
    Mar 18, 2025 · Knowing when to use a polyfill for a feature depends on its availability across browsers, and Baseline can be helpful in making that determination.What Are The Disadvantages... · Determine Your Baseline... · When And When Not Polyfill A...
  73. [73]
    Worker - Web APIs - MDN Web Docs
    Jul 24, 2024 · The Worker interface of the Web Workers API represents a background task that can be created via script, which can send messages back to its creator.Using Web Workers · Web Workers API · Worker() constructor · Service WorkersMissing: multi- threading single- threaded<|control11|><|separator|>
  74. [74]
  75. [75]
    josdejong/workerpool: Offload tasks to a pool of workers on ... - GitHub
    workerpool offers an easy way to create a pool of workers for both dynamically offloading computations as well as managing a pool of dedicated workers.Missing: 2010 | Show results with:2010
  76. [76]
    JavaScript | 2022 | The Web Almanac by HTTP Archive
    Sep 26, 2022 · Web workers​​ Figure 2.19. The number of mobile pages using web workers. It's heartening to see that 12% of mobile and desktop pages currently ...
  77. [77]
    The service worker lifecycle | Articles - web.dev
    Sep 29, 2016 · The first event a service worker gets is install . It's triggered as soon as the worker executes, and it's only called once per service worker.The first service worker · Updating the service worker · Avoid changing the URL of...
  78. [78]
    Service Workers - W3C
    Mar 6, 2025 · Service workers are generic, event-driven, time-limited script contexts that run at an origin, acting as a type of web worker that wakes to ...
  79. [79]
    Service Worker API - MDN Web Docs
    Aug 19, 2025 · Service workers essentially act as proxy servers that sit between web applications, the browser, and the network (when available).Using Service Workers · ServiceWorker · Register() method · FetchEvent
  80. [80]
    Workers overview | Articles - web.dev
    Dec 8, 2020 · This overview explains how web workers and service workers can improve the performance of your website, and when to use a web worker versus a service worker.
  81. [81]
    Service Workers - W3C
    Feb 5, 2015 · The service worker is a generic entry point for event-driven background processing in the Web Platform that is extensible by other specifications.
  82. [82]
    Service Workers | Can I use... Support tables for HTML5, CSS3, etc
    "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.<|control11|><|separator|>
  83. [83]
    SharedArrayBuffer - JavaScript - MDN Web Docs
    Jul 10, 2025 · Shared memory can be created and updated simultaneously in workers or the main thread. Depending on the system (the CPU, the OS, the Browser) it ...Window: crossOriginIsolated · byteLength · Growable · maxByteLengthMissing: multi- | Show results with:multi-
  84. [84]
    Cross-Origin-Opener-Policy (COOP) header - HTTP - MDN Web Docs
    Jul 4, 2025 · Examples. Features that depend on cross-origin isolation. Certain features, such as access to SharedArrayBuffer objects or using Performance.
  85. [85]
    Cross-Origin-Embedder-Policy (COEP) header - MDN Web Docs
    Aug 18, 2025 · The HTTP Cross-Origin-Embedder-Policy (COEP) response header configures the current document's policy for loading and embedding cross-origin resources.
  86. [86]
    Atomics - JavaScript - MDN Web Docs
    Jul 10, 2025 · The Atomics namespace object contains static methods for carrying out atomic operations. They are used with SharedArrayBuffer and ArrayBuffer objects.Atomics.notify() · Atomics.add() · Atomics.wait() · Atomics.waitAsync()
  87. [87]
    Feature Status - WebAssembly
    WebAssembly has been gaining new features through the standardization process. For the complete list of current proposals and their respective stages, check ...
  88. [88]
    WebAssembly.Memory() constructor - MDN Web Docs - Mozilla
    Jun 23, 2025 · The shared attribute is only documented in the Threading proposal for WebAssembly and not part of the official specs. Browser compatibility.
  89. [89]
    Scaling multithreaded WebAssembly applications with mimalloc and ...
    Jan 30, 2025 · This guide shows how these features can lead to speed improvements of 10 times or more in some cases.