---
schema_version: "1"
id: 8da04ddeec562ce1edf457e7f2cf6b73c2a957583bce1339307ff9abfe0ccf3f
title: Understand How LWS Architecture Affects Component Performance
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/lwc/lightning-components-security/guides/lws/lws-performance.md
canonical_url: https://developer.salesforce.com/docs/platform/lightning-components-security/guide/lws-performance.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 3247b3c7faa1cc35a681142e91fe3b26608120b0593fe17658bccf63f94d87cd
products:
  - Security for Lightning Components
  - lwc
---
# Understand How LWS Architecture Affects Component Performance

Custom Lightning components always run with either Lightning Locker or Lightning Web Security (LWS). If LWS is disabled, Lightning Locker is enabled. In many cases, components exhibit better performance running with LWS than with Lightning Locker. However, sometimes LWS can have a noticeable performance impact on your components. To give you insight about why your components can run into performance issues with LWS, let’s dig a little deeper into the LWS architecture.

## Security Concerns With Multiple Namespaces

A Lightning page can include components created by multiple companies. For example, components created by an organization’s developer team must run concurrently with components created by Salesforce. If you distribute components in managed packages, your components must run concurrently with components created by Salesforce and the components of the customer who installs your packages.

The components from each origin have a unique namespace, which is a Salesforce requirement for components to be installed into an org. Without a security layer such as Lightning Locker or LWS, the components all have access to the same browser resources and data as if they were all in the same namespace. Such is the nature of all web applications. The chances for unintentional interference between components from different namespaces are high. For example, if a component in namespace `c` changes a global object, the object is mutated for all the components and for the Salesforce platform. Code that tries to use that object after it’s mutated can potentially be unable to perform the intended action. If a component creates data in the page for the use of its namespace, components in other namespaces can also access the data and change it.

For example, suppose a component changes a global function as shown in this code sample.

```javascript
Object.prototype.toString = function () {
  return "";
};
```

The change affects all other objects on the page. This other code sample that’s using that mutated global function always returns the unexpected value.

```javascript
if (myObj.toString() === "expected") {
  // We got the expected value
} else {
  // We got an unexpected value
}
```

## LWS Uses Virtualization to Isolate Namespaces

To understand the reasons for performance issues that components can have when running with LWS, you must be familiar with the concepts discussed in [Virtualization of the Browser](https://developer.salesforce.com/docs/platform/lightning-components-security/guide/lws-architecture.md#virtualization-of-the-browser).

As a browser virtualization engine, LWS creates virtual environments called sandboxes for each namespace. A namespace sandbox is a copy of the host environment that can only be accessed by components that belong to the namespace.

By default, custom components use the namespace `c`, and LWS creates a `c` sandbox for them. Let’s say that your Lightning page uses your custom components, and also uses components from a managed package that uses the namespace `other`. LWS isolates code that’s running in the namespace `c` sandbox from side effects and changes of code running in the namespace `other` sandbox, and vice versa. If you add components from another namespace called `third` to the page, LWS creates another sandbox for the `third` namespace, and isolates the code from the `c` and `other` namespace sandboxes.

Most importantly, LWS isolates all the sandboxes from the browser’s host environment. The client side of the Salesforce platform runs in the host environment. The platform includes technologies such as the Lightning framework for Aura and Lightning Web Components, Lightning Data Service, and LWS itself. These platform technologies must be protected from malicious or inadvertent access by non-platform code.

The most critical JavaScript object that must be protected in the host environment is the DOM’s `window` global object. Components from namespace `third` must not be able to intentionally or unintentionally modify global variables that could have a negative side effect on the components from the `c` or `other` namespaces. Even more importantly, a non-platform component must not be able to make changes that affect platform code like Aura or LWC. Such changes could have an impact on the entire application.

For example, imagine that an LWC `third-some-cmp` modified some `Array.prototype` functions. If the LWS sandboxes weren’t in effect, those changes affect the host environment, and components like `c-example-cmp` and `other-cmp-example`. When code in the host environment or the other namespaces uses the modified `Array.prototype` functions to manipulate data in arrays, unexpected or harmful behavior can occur.

As another example, imagine some JavaScript from module `other/myFunctions` modifying a cookie called `session`. A component `c-example-cmp` also modifies a cookie called `session`. Without LWS sandboxing, code from different namespaces can accidentally read or modify the same cookie.

## How LWS Enables Interaction of Namespaces

LWS creates a virtual browser environment in a sandbox for each namespace, and allows only namespace code to execute inside this sandbox. At the same time, LWS allows code running inside a sandbox to interact with code running in another sandbox or with the browser’s host environment and the DOM.

This diagram shows the browser host environment and objects related to it in blue. The sandboxes and objects related to them are in red.

![Diagram showing proxy objects in sandboxes and host environment](https://developer.salesforce.com/media/lws_proxy_diagram.png)

In order to allow [marshaled access](https://developer.salesforce.com/docs/platform/lightning-components-security/guide/%3Chttps://en.wikipedia.org/wiki/Marshalling_(computer_science)>) to objects between sandboxes and the host environment, LWS uses [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) objects. Here are a few scenarios using proxies that this diagram demonstrates.

- The solid blue X object ![Object called X created in host environment](https://developer.salesforce.com/media/lws-x-blue-solid.png) is created in and owned by the host environment. LWS allows `c` namespace components to access this object by creating the dashed blue X proxy ![Proxy for X object](https://developer.salesforce.com/media/lws-x-blue-dash.png) in the sandbox. If code in sandbox `c` modifies the blue X proxy ![Proxy for X object](https://developer.salesforce.com/media/lws-x-blue-dash.png) in any way, those modifications are only reflected inside sandbox `c`, and not in the target blue X object ![Target object called X](https://developer.salesforce.com/media/lws-x-blue-solid.png) owned by the host environment.
- The solid red Y object ![Object called Y created in c sandbox](https://developer.salesforce.com/media/lws-y-red-solid.png) is created in and owned by code in namespace `c`. Code in sandbox `c` can pass this object as an argument to a function that’s owned by the host environment. For example, the host environment function can be owned by LWC or Lightning Data Service. LWS provides a dashed red Y proxy object ![Proxy for Y object in host environment](https://developer.salesforce.com/media/lws-y-red-dash.png) for the host environment’s function to interact with.
- If code in sandbox `c` interacts with the solid red Z object ![Object Z created in other sandbox](https://developer.salesforce.com/media/lws-z-red-solid.png) that’s owned by namespace `other`, LWS provides an indirect Z proxy ![Indirect Z proxy created in c sandbox](https://developer.salesforce.com/media/lws-z-red-dot.png) for sandbox `c` code to interact with it. The proxy is indirect because it doesn’t interact directly with the target red Z object ![Target Z object](https://developer.salesforce.com/media/lws-z-red-solid.png). Instead, the indirect Z proxy interacts with the dashed red Z proxy ![Z proxy in host environment](https://developer.salesforce.com/media/lws-z-red-dash.png) in the host environment. LWS provides the dashed red Z proxy ![Z proxy in host environment](https://developer.salesforce.com/media/lws-z-red-dash.png) for code to interact with red Z object ![Target Z object](https://developer.salesforce.com/media/lws-z-red-solid.png) outside of the `other` namespace.
- The solid red W object ![Object W in third sandbox](https://developer.salesforce.com/media/lws-w-red-solid.png) is created in and owned by code in namespace `third`, so the dashed red W proxy object ![Proxy W in host environment](https://developer.salesforce.com/media/lws-w-red-dash.png) is created in the host environment. The indirect W proxy ![Indirect proxy W in other namespace](https://developer.salesforce.com/media/lws-w-red-dot.png) in namespace `other` enables code in that namespace to interact with the target W object ![Object W in third sandbox](https://developer.salesforce.com/media/lws-w-red-solid.png) through the W proxy ![Proxy W in host environment](https://developer.salesforce.com/media/lws-w-red-dash.png) in the host environment.

In summary, LWS provides:

- a proxy object in a sandbox whenever code in the sandbox interacts with an object that’s owned by the host environment
- a proxy object in the host environment whenever code in the host environment interacts with an object that’s owned by a sandbox
- an indirect proxy object in a sandbox whenever code in the sandbox interacts with an object that’s owned by another sandbox

In any sandbox environment, when code modifies a proxy object, the proxy target remains unchanged. LWS protects the target object, whether the target object is also a proxy object or the original object.

**tip:** LWS uses the proxy objects to implement the [distortions](https://developer.salesforce.com/docs/platform/lightning-components-security/guide/lws-architecture.md#distortions) to prevent behavior that’s not secure.

## Performance Side Effects of LWS Proxies

The use of proxies has a performance cost due to the extra processing required. This cost is negligible when there are a few thousand proxies, but as the number of proxies grows into the tens of thousands, the performance impact becomes observable.

### Effects on Applications That Handle Large Quantities of Data

Salesforce testing shows that if an application is already pushing limits that lead to degraded performance, LWS magnifies this effect. For instance, consider an app or component that’s handling a large collection of objects in the tens of thousands. When the large collection is traversed and processed with Lightning Locker enabled, you likely don’t notice performance issues. However, if LWS is enabled, the performance degradation can be noticeable.

This example shows component code that uses the global object [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set). Global objects are owned by the host environment, so LWS creates a proxy Set object in the component’s namespace sandbox. Each access of the Set object goes through the proxy object, which increases the processing cost.

```javascript
// The performance degradation of new Set(bigArray)
// is not that noticeable
const bigArray = [
  /* array with 1,000 entries */
];
const bigSet = new Set(bigArray);

// The performance degradation of new Set(hugeArray)
// is very noticeable
const hugeArray = [
  /* array with 100,000 entries */
];
const hugeSet = new Set(hugeArray);
```

To extend this example, consider a custom component that retrieves a large amount of data from Lightning Data Service or an Apex controller.

```javascript
import { LightningElement, wire, track } from 'lwc';
import getCustomData from '@salesforce/apex/CustomController.getCustomData';

export default class CustomDataProcess extends LightningElement {
    @track customData;
    @track error;
    @wire(getCustomData)
    processCustomData({ error, data }) {
        for (let i = 0; i < data.length; i++) {
            data[i] += data[i] + 1;
            // more code for getting or setting the array elements
        }
    }

    processCustomDataNoWire() {
        getCustomData().then(data =>
            for (let i = 0; i < data.length; i++) {
                data[i] += data[i] + 1;
                // more code for getting or setting the array elements
            }
        )
    }

}
```

The data retrieved from the Apex controller is equivalent to the solid blue X object ![Object called X created in host environment](https://developer.salesforce.com/media/lws-x-blue-solid.png) discussed in [How LWS Enables Interaction of Namespaces](#how-lws-enables-interaction-of-namespaces), meaning that it’s created in and owned by the host environment. To access the data from within the custom code, which exists in the component’s namespace sandbox, each call requires passing through a blue X proxy object ![Proxy for X object](https://developer.salesforce.com/media/lws-x-blue-dash.png). With large quantities of data, this extra processing leads to performance degradation.

To optimize performance, follow these guidelines.

- Move the operation and calculation into the Apex controller so the processing is done on the server side. Don’t perform it on the client side.
- To continue processing on the client side, clone the data so that it’s equivalent to a solid red Y object ![Object called Y created in c sandbox](https://developer.salesforce.com/media/lws-y-red-solid.png) instead of a solid blue X object ![Object called X created in host environment](https://developer.salesforce.com/media/lws-x-blue-solid.png). If the data is created in the component’s namespace sandbox instead of in the host environment, then creation of a blue X proxy object ![Proxy for X object](https://developer.salesforce.com/media/lws-x-blue-dash.png) isn’t required.

Here’s the component code adjusted so that the data is cloned into the component’s namespace sandbox before processing.

```javascript

import { LightningElement, wire, track } from 'lwc';
import getCustomData from '@salesforce/apex/CustomController.getCustomData';

export default class CustomDataProcess extends LightningElement {
    @track customData;
    @track error;

    @wire(getCustomData)
    processCustomData({ error, data }) {
        // Clone the blue data object into red.
        let redData = JSON.parse(JSON.stringify(data));
        for (let i = 0; i < redData.length; i++) {
            redData[i] += redData[i] + 1;
            // more code for getting or setting the array elements
        }
    }

    processCustomDataNoWire() {
        getCustomData().then(data =>
            // Clone the blue data object into red.
            let redData = JSON.parse(JSON.stringify(data));
            for (let i = 0; i < redData.length; i++) {
                redData[i] += redData[i] + 1;
                // more code on getting or setting the array elements
            }
        )
    }
}
```

### Effects on Applications with a Large Number of Components

Another case where LWS can degrade performance is an application that instantiates a large number of components or DOM elements. In particular, if all the components are rendered and present in the DOM at the same time, you can notice performance degradation. DOM operations are expensive, and you must be mindful about what you do in the DOM and how often you do it.

Suppose an app is using a third-party component that performs many DOM operations, and the app spawns many instances of this component. This activity by itself can push the limits of the browser. With LWS disabled, the performance effects can take a long time to see. With LWS enabled, you see the performance effects sooner.

See this article on web.dev [How large DOM sizes affect interactivity, and what you can do about it](https://web.dev/articles/dom-size-and-interactivity) for more information.

## Improvements to LWS Performance

Salesforce continues to examine the effects of LWS on the performance of your custom components. We’re working on ways to improve performance and achieve the same level of security for LWS.

In the meantime, we recommend that you examine your code to find opportunities to reduce heavy DOM usage. When creating large collections of objects, minimize the use of global objects such as Set, Map, and TypedArray. Use plain JavaScript objects instead.
