# Event Failover

When event delivery fails after all retry attempts, Stream can automatically persist the failed event to a storage backend you control. This ensures no events are lost during outages in your endpoint.

Currently, Google Cloud Storage (GCS) is supported as a failover storage backend.

## How it Works

1. Stream attempts to deliver an event to your endpoint
2. If all delivery retries are exhausted, the event is written to your configured GCS bucket
3. The event is stored as a JSON file containing the full event payload, metadata about the failure, and the original endpoint URL

You can then process these failed events at your own pace by reading them from GCS.

## Configuration

To enable failover, add a `failover_config` to your event hook:

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await client.updateAppSettings({
  event_hooks: [
    {
      enabled: true,
      hook_type: "webhook",
      webhook_url: "https://example.com/webhooks/stream",
      event_types: ["message.new"],
      failover_config: {
        type: "gcs",
        gcs_bucket: "my-failover-bucket",
        gcs_path: "stream/failed-events",
        gcs_credentials: '{"type":"service_account","project_id":"..."}',
      },
    },
  ],
});
```

</codetabs-item>

</codetabs>

<admonition type="caution">

GCS credentials are validated when you save the configuration. Make sure the service account JSON key is valid and has write access to the specified bucket before updating your app settings.

</admonition>

<admonition type="info">

Failover is currently supported for webhook hooks. Support for SQS and SNS hooks is planned.

</admonition>

## Configuration Options

| Option          | Type   | Description                                               | Required |
| --------------- | ------ | --------------------------------------------------------- | -------- |
| type            | string | Storage backend type. Currently only `"gcs"` is supported | Yes      |
| gcs_bucket      | string | The name of your GCS bucket                               | Yes      |
| gcs_credentials | string | GCS service account JSON key as a string                  | Yes      |
| gcs_path        | string | Optional prefix for the object path inside the bucket     | No       |

## GCS Permissions

The service account used in `gcs_credentials` needs the following permissions on the target bucket:

- `storage.objects.create`
- `storage.objects.get`

The simplest way is to grant the **Storage Object Creator** (`roles/storage.objectCreator`) role to the service account on the bucket.

## Storage Format

Failed events are stored as JSON files in your GCS bucket with the following path structure:

```text
{gcs_path}/{yyyy}/{mm}/{dd}/{timestamp}-{event_type}-{hook_id}.json
```

For example:

```text
stream/failed-events/2026/04/03/1743667200-message.new-a1b2c3d4.json
```

Each file contains a JSON envelope with the following fields:

```json
{
  "original_hook_id": "hook-123",
  "original_webhook_url": "https://example.com/webhooks/stream",
  "event_type": "message.new",
  "error_message": "HTTP 500: Internal Server Error",
  "failed_at": "2026-04-03T12:00:00Z",
  "payload": {
    "type": "message.new",
    "cid": "messaging:general",
    "message": { ... },
    "user": { ... }
  }
}
```

| Field                | Description                                           |
| -------------------- | ----------------------------------------------------- |
| original_hook_id     | The ID of the event hook that failed                  |
| original_webhook_url | The endpoint URL that was unreachable                 |
| event_type           | The type of event that failed to deliver              |
| error_message        | The error returned by the last delivery attempt       |
| failed_at            | ISO 8601 timestamp of when the failure was recorded   |
| payload              | The full event payload that would have been delivered |

## Disabling Failover

To remove the failover configuration, update the hook without the `failover_config` field:

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await client.updateAppSettings({
  event_hooks: [
    {
      enabled: true,
      hook_type: "webhook",
      webhook_url: "https://example.com/webhooks/stream",
      event_types: [],
      // no failover_config = failover disabled
    },
  ],
});
```

</codetabs-item>

</codetabs>


---

This page was last updated at 2026-04-03T17:26:54.158Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/react/event_failover/](https://getstream.io/chat/docs/react/event_failover/).