> ## Documentation Index
> Fetch the complete documentation index at: https://docs.daily.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Network events

> Events for network quality changes, connection interruptions, CPU load, and prejoin test results.

These events fire when network quality or connection state changes, when CPU load fluctuates, and when prejoin tests complete.

***

## network-quality-change

Fires when the network quality assessment changes.

<Warning>
  As of daily-js 0.77.0, `threshold` and `quality` are deprecated in favor of `networkState` and `networkStateReasons`. Version 0.77.0 also added the `stats` bundle to the event payload.
</Warning>

<ResponseField name="action" type="string">
  Always `"network-quality-change"`.
</ResponseField>

<ResponseField name="callClientId" type="string">
  The ID of the call client instance that emitted this event.
</ResponseField>

<ResponseField name="networkState" type="string">
  Current network assessment: `'good'`, `'low'`, or `'bad'`.
</ResponseField>

<ResponseField name="networkStateReasons" type="string[]">
  Reasons contributing to a `'low'` or `'bad'` state. Possible values include `'sendPacketLoss'` and `'recvPacketLoss'`. Omittied if `networkState` is `'good'`.
</ResponseField>

<ResponseField name="stats" type="object">
  The latest network stats bundle. Shape matches the return value of [`getNetworkStats()`](/reference/react-native/instance-methods/get-network-stats).
</ResponseField>

<ResponseField name="threshold" type="string" deprecated>
  Deprecated. Use `networkState` instead.
</ResponseField>

<ResponseField name="quality" type="number" deprecated>
  Deprecated. Use `networkState` instead.
</ResponseField>

```json theme={null}
// Example event object
{
  "action": "network-quality-change",
  "callClientId": "17430118453690.12992179309705953",
  "networkState": "bad",
  "networkStateReasons": ["sendPacketLoss", "recvPacketLoss"],
  "stats": {
    "averageNetworkRoundTripTime": 0.01992261904761905,
    "latest": {
      "audioRecvPacketLoss": 0.15053763440860216,
      "videoSendBitsPerSecond": 1589251.349980054,
      "..."
    }
  }
}
```

```javascript theme={null}
call.on('network-quality-change', ({ networkState, networkStateReasons }) => {
  if (networkState === 'bad') {
    showNetworkWarning(networkStateReasons);
  }
});
```

***

## network-connection

Fires when a network connection is established or interrupted. Every call uses two connections simultaneously:

* **`signaling`** — carries call setup and management. If interrupted and not reconnected within \~20 seconds, the participant is ejected from the call.
* **`peer-to-peer`** or **`sfu`** — carries audio and video. A call uses one or the other, never both. All calls default to SFU topology, including 1:1 calls. See [P2P vs SFU calls](/docs/guides/architecture-and-monitoring/intro-to-video-arch#the-architecture-of-a-room-p2p-vs-sfu-calls) for details. Both reconnect automatically as long as `signaling` is alive.

<ResponseField name="action" type="string">
  Always `"network-connection"`.
</ResponseField>

<ResponseField name="callClientId" type="string">
  The ID of the call client instance that emitted this event.
</ResponseField>

<ResponseField name="type" type="string">
  The connection type: `'signaling'`, `'peer-to-peer'`, or `'sfu'`.
</ResponseField>

<ResponseField name="event" type="string">
  The connection event: `'connected'` or `'interrupted'`.
</ResponseField>

<ResponseField name="session_id" type="string">
  Present for `peer-to-peer` connections. The remote peer's `session_id`.
</ResponseField>

<ResponseField name="sfu_id" type="string">
  Present for `sfu` connections. The SFU server ID — useful for debugging and support reports.
</ResponseField>

```json theme={null}
// Example: signaling connected
{
  "action": "network-connection",
  "type": "signaling",
  "event": "connected",
  "callClientId": "17225364729060.9442072768918943"
}
```

```json theme={null}
// Example: peer-to-peer connected
{
  "action": "network-connection",
  "type": "peer-to-peer",
  "event": "connected",
  "session_id": "123e4567-e89b-12d3-a456-426655440000",
  "callClientId": "17225364729060.9442072768918943"
}
```

```json theme={null}
// Example: sfu interrupted
{
  "action": "network-connection",
  "type": "sfu",
  "event": "interrupted",
  "sfu_id": "server-id",
  "callClientId": "17225364729060.9442072768918943"
}
```

***

## cpu-load-change

<Warning>
  The `cpu-load-change` event applies to video calls only.
</Warning>

Fires when the CPU load state changes. When `cpuLoadState` is `'high'`, consider lowering outgoing video quality via [`updateSendSettings()`](/reference/react-native/instance-methods/update-send-settings), requesting a lower simulcast layer via [`updateReceiveSettings()`](/reference/react-native/instance-methods/update-receive-settings), or reducing video subscriptions in large calls.

<ResponseField name="action" type="string">
  Always `"cpu-load-change"`.
</ResponseField>

<ResponseField name="callClientId" type="string">
  The ID of the call client instance that emitted this event.
</ResponseField>

<ResponseField name="cpuLoadState" type="string">
  Current CPU load assessment: `'low'` or `'high'`.
</ResponseField>

<ResponseField name="cpuLoadStateReason" type="string">
  The reason for the current state: `'none'` (load is low), `'encode'` (video encoding), `'decode'` (video decoding), or `'scheduleDuration'` (Daily code not completing within its scheduled interval).
</ResponseField>

```json theme={null}
// Example event object
{
  "action": "cpu-load-change",
  "cpuLoadState": "low",
  "cpuLoadStateReason": "none",
  "callClientId": "17225364729060.9442072768918943"
}
```

***

## test-completed

Fires when a prejoin test completes.

<Note>
  This event fires when a prejoin test method completes.
</Note>

<ResponseField name="action" type="string">
  Always `"test-completed"`.
</ResponseField>

<ResponseField name="callClientId" type="string">
  The ID of the call client instance that emitted this event.
</ResponseField>

<ResponseField name="test" type="string">
  Which test completed: `'call-quality'`, `'p2p-call-quality'`, `'network-connectivity'`, or `'websocket-connectivity'`.
</ResponseField>

<ResponseField name="results" type="object">
  The test results. Shape matches the return type of the corresponding test method.
</ResponseField>

```json theme={null}
// Example: call-quality test completed
{
  "action": "test-completed",
  "test": "call-quality",
  "results": {
    "result": "good",
    "data": {
      "maxRoundTripTime": 0.247,
      "avgRoundTripTime": 0.13130370781129388,
      "avgSendPacketLoss": 0.0036800000000000014,
      "avgAvailableOutgoingBitrate": 2060985,
      "avgSendBitsPerSecond": 1778201
    },
    "id": "47dc6b22-2909-46f3-8d0f-ec1f3807046c",
    "secondsElapsed": 22
  },
  "callClientId": "17225364729060.9442072768918943"
}
```

***

## See also

<CardGroup>
  <Card title="Methods" icon="code" iconType="solid">
    * [getNetworkStats()](/reference/react-native/instance-methods/get-network-stats)
    * [updateSendSettings()](/reference/react-native/instance-methods/update-send-settings)
    * [updateReceiveSettings()](/reference/react-native/instance-methods/update-receive-settings)
    * [testPeerToPeerCallQuality()](/reference/react-native/instance-methods/test-peer-to-peer-call-quality)
  </Card>

  <Card title="Guides" icon="book-open" iconType="solid">
    * [Events](/docs/daily-js/concepts/events)
    * [Network quality](/docs/daily-js/guides/network-quality)
    * [Logging and metrics](/docs/guides/architecture-and-monitoring/logging-and-metrics)
  </Card>
</CardGroup>
