# Voice JavaScript SDK: Edge Locations

Twilio Voice JavaScript SDK lets you select the specific [Twilio data center edge locations](/docs/global-infrastructure/edge-locations) used when your Twilio Device connects to Twilio. Network communication to and from Twilio will originate/terminate from the fixed, static IP address ranges listed for each edge location. Refer to these ranges if you need to configure your local network to allow communication or apply Quality of Service routing rules to communication with Twilio.

> \[!WARNING]
>
> Twilio [edge locations](/docs/global-infrastructure/edge-locations) were added in version 1.11. Prior releases used a [parameter named `region` that has now been deprecated](/docs/global-infrastructure/edge-locations/legacy-regions).

## Edge Location information for Twilio Voice JavaScript SDK

By default, the [Twilio Voice JavaScript SDK](/docs/voice/sdks/javascript) will use Twilio's Global Low Latency (the `roaming` edge location) routing capability to determine which data center is closest to your user, establishing a connection through Twilio's nearest point of presence.

Global Low Latency uses latency-based DNS lookups to determine the nearest data center. You may want to override this in some cases, especially when your users are working from a fixed location and using a DNS server in another [edge location](/docs/global-infrastructure/edge-locations).

> \[!NOTE]
>
> GLL (`roaming` edge location) requires the upstream DNS to support RFC 7871. See [GLL requirements](/docs/voice/sdks/network-connectivity-requirements) for more information.

If you are operating a restricted network that requires allowing of media IPs, our recommendation is to specify the [edge location](/docs/global-infrastructure/edge-locations) in your application. Twilio will continue to expand our Global Low Latency (the `roaming` edge location) footprint in the future by adding more edges with different IP ranges and leaving the edge selection up to Global Low Latency could result in connections being established to edges that are not allowed by your infrastructure which may result in one-way audio or call set up failures.

Use any one of the [available edge locations](/docs/global-infrastructure/edge-locations) as the `edge` parameter. Leaving the value undefined will cause Twilio to default to its Global Low Latency routing, which cause the `Device` to establish its connection to the Twilio edge closest to the user.

## Edges

> \[!NOTE]
>
> For connectivity and bandwidth requirements including IP address list and ports see [Voice Platform SDKs' Network Connectivity Requirements](/docs/voice/sdks/network-connectivity-requirements)

### Example Usage

The examples below show two methods for setting an edge location.

**Option 1** instantiates a `new Twilio.Device` with `token` and `options` arguments.

**Option 2** instantiates a `new Twilio.Device` without the `options` argument. With this method, you can update the `device` options with `device.updateOptions(options)`.

#### Force connections through Twilio Ireland

Option 1:

```bash
const device = new Twilio.Device(token, { edge: "dublin" });
```

Option 2:

```bash
const device = new Twilio.Device(token);
device.updateOptions({ edge: "dublin" });
```

#### Force connections through Twilio US East Coast edge over your private Interconnect connection to that edge

Option 1:

```bash
const device = new Twilio.Device(token, { edge: "ashburn-ix" });
```

Option 2:

```bash
const device = new Twilio.Device(token);
device.updateOptions({ edge: "ashburn-ix"});
```

#### Let Twilio choose the nearest edge

```bash
const device = new Twilio.Device(token);
```

## Edge Fallback

By default, the SDK automatically reconnects the WebSocket connection to the same edge location when it is unreachable, or when the SDK encounters a network error that results in a WebSocket disconnect. But if `Twilio.Device.Options.edge` parameter is supplied as an array of edge names, the SDK will enable automatic Edge fallback functionality. The diagram below illustrates the logic that is executed to perform the fallback.

![Flowchart showing edge fallback process with steps for connection success and error handling.](https://docs-resources.prod.twilio.com/c3bb8319fb1ac304874b75772572737af044cad969ce65d2247b3ecb31d77a78.png)

During initialization, the SDK will use the first edge name in the Twilio.Device.Options.edge array.

If the SDK encounters an error that results in a WebSocket disconnect with error code [1006 or 1015](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent), the SDK will attempt reconnection to the next Edge in the array using an exponential backoff timer with an initial value of 1+random(5) and a maximum of 20 seconds. This maximum delay can be configured via Twilio.Device.Options.backoffMaxMs parameter.

If the SDK encounters an error while already connected to an edge server, the SDK will try to reconnect to the same edge once before attempting to connect to the next edge.

The following table provides common scenarios for when a fallback may occur:

| Scenario                                                                                                                                                                                                                                                                                                    | Expected Behavior                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Initialize with edge: \["ashburn"]                                                                                                                                                                                                                                                                          | This behaves exactly the same as initializing with edge: "ashburn". In this scenario, the SDK will always attempt to reconnect to ashburn whenever the WebSocket is disconnected.                                                                                                                                                                                                                                                                                            |
| The first edge name specified in the edge array is unreachable. <br /><br />• ashburn becomes unreachable <br />• Initialize with edge: \["ashburn", "sydney"]                                                                                                                                              | The SDK will attempt to connect to ashburn. Since ashburn is unreachable, the attempt will fail. The SDK will then attempt to connect to sydney.                                                                                                                                                                                                                                                                                                                             |
| All edge endpoints are unreachable, then one region becomes available after a few seconds. <br /><br />• ashburn, sydney, and dublin becomes unreachable <br />• Initialize with edge: \["ashburn", "sydney", "dublin"] <br />• sydney becomes available, and the rest of the regions are still unreachable | The SDK will attempt to connect to ashburn. Since ashburn is unreachable, the attempt will fail. The SDK will then attempt sydney and will fail again. Then dublin will be attempted and fail. Once the SDK reaches the last edge name, it will loop back to the first edge name ashburn, and will keep cycling through the edge names until one edge endpoint becomes available. If sydney becomes available, the SDK will be connected to sydney once the loop reaches it. |
| All edges are available and the edge the SDK is connected to suddenly becomes unreachable. <br /><br />• Initialize with edge: \["ashburn", "sydney", "dublin"] <br />• SDK is now connected to ashburn. <br />• ashburn goes down and becomes unreachable                                                  | If you are connected to ashburn and it suddenly becomes unreachable, the SDK will attempt to connect to ashburn once. If the attempt fails, the SDK will attempt to connect to the next edge, which is sydney.                                                                                                                                                                                                                                                               |

It's important to note that "unreachable" in these scenarios means the SDK failed to establish a WebSocket connection to the edge endpoint which resulted in error code [1006 or 1015](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent). The error code 1015 is a WebSocket close event which is raised when the connection fails to perform a TLS handshake. This happens if the server certificate is invalid or cannot be verified. While the error code 1006 is raised when the connection was dropped unexpectedly and there is no close frame received from the server. The following are common issues that causes 1006:

* The domain name cannot be resolved by the DNS
* The network cannot reach the endpoint due to, for example, a misconfigured firewall
* The client becomes offline due to, for example, the local device losing network connectivity
* In an unlikely and very rare scenario, the Edge and standby servers are down

## Edge Fallback and Signaling Reconnection

Signaling connectivity loss is the loss of the signaling websocket, and it usually only occurs when a user experiences a change in network during a call. As of v2.1.0 of the Voice JavaScript SDK, signaling reconnection is fully supported via the [DeviceOptions.maxCallSignalingTimeoutMs](/docs/voice/sdks/javascript/twiliodevice#deviceoptions) property included in v2.1.0+ of the SDK. A Twilio.Device will now attempt to reconnect to a lost websocket for up to 30 seconds.

A lost websocket connection can only be reestablished on its original edge. The default edge fallback behavior of the SDK will cause the `Twilio.Device` to a connection to the original edge one time, and if that attempt fails, it will attempt a connection on the next edge in the `DeviceOptions.edge` array. If it connects to a new edge, however, reestablishing that lost websocket connection is no longer possible. This will cause the call to disconnect.

You can temporarily pause edge fallback during these signaling reconnection attempts using the `DeviceOptions.maxCallSignalingTimeoutMs` property. This property sets how long your device should try to reconnect to the original edge during signaling reconnection attempts.

Since the `Twilio.Device` can attempt to restore signaling connectivity for up to 30 seconds (30000 milliseconds), you likely will want to set your `DeviceOptions.maxCallSignalingTimeoutMs` property to `30000`. This means that your `Twilio.Device` will not try to connect to any other edge during the entirely of the reconnection attempt.

```javascript
const deviceOptions = {
  edge: ['ashburn', 'sydney'],
  maxCallSignalingTimeoutMs: 30000
}

const device = new Twilio.Device(token, deviceOptions);
```
