---
title: Agent notifications
slug: feature-experimentation/docs/agent-notifications
docTags: 
createdAt: 2026-08-05T20:40:00.000Z
---

For details on the notification types, what causes them to be triggered, and the data they provide, see [Configure notification listener documentation for the Go SDK](docId\:t5MKaa3LIkBM5ovyv7XYn).

## Configuration

By default, the notifications endpoint is disabled. To enable it, update the `config.yaml` file.

```yaml
# config.yaml
api:
    enableNotifications: true
```

Or, enable it by configuring an environment variable.

```shell
# set an env. variable
export OPTIMIZELY_API_ENABLENOTIFICATIONS=1
```

## Usage

Send a `GET` request to `/v1/notifications/event-stream` to subscribe.

```curl
curl -N -H "Accept:text/event-stream" -H "X-Optimizely-Sdk-Key:<YOUR SDK KEY>"\
  http://localhost:8080/v1/notifications/event-stream
```

This connection remains open, and any notifications triggered by other requests received by Agent are pushed as events to this stream. Try sending requests to [/v1/activate](docId:6l8SJAb2LbuKwUjW38qmv) or [/v1/track](docId:7I5iVwVDKg33COiiEOtQu) to see notifications being triggered.

### Filter query parameter

To subscribe only to a particular category of notifications, add a `filter` query parameter. For example, to subscribe only to Decision notifications

```curl
# filter on decision notifications
curl -N -H "Accept:text/event-stream" -H "X-Optimizely-Sdk-Key:<YOUR SDK KEY>"\
  http://localhost:8080/v1/notifications/event-stream?filter=decision
```

When the Agent is operating in High Availability (HA) mode, you need to enable notification sync to get notifications from the nodes in an HA configuration. A PubSub system (Redis) is now used to ensure consistent retrieval of notification events across all nodes in an HA configuration.

The following is an example of how you can enable the notification sync with Redis:

```yaml
## synchronization should be enabled when features for multiple nodes like notification streaming are deployed
synchronization:
    pubsub:
        redis:
            host: "localhost:6379"
            password: ""
            database: 0
    ## if notification synchronization is enabled, then the active notification event-stream API
    ## will get the notifications from available replicas
    notification:
        enable: true
        default: "redis"
```

## Example

For a runnable Python example, see [examples/notifications.py](https://github.com/optimizely/agent/tree/master/examples) in GitHub.

## Notification sync: Redis Streams vs Redis Pub/Sub

### High Availability mode

When the Agent is operating in High Availability (HA) mode, you need to enable notification sync to get notifications from all nodes in an HA configuration. Agent uses Redis to ensure consistent retrieval of notification events across all nodes.

Agent **automatically detects your Redis version** and chooses the best notification system:

- **Redis >= 5.0** – Uses Redis Streams (persistent, batched delivery with acknowledgment).
- **Redis \< 5.0** – Uses Redis Pub/Sub (simple, fire-and-forget).
- **Detection fails** – Falls back to Redis Pub/Sub (safe default).

### Configuration

```yaml
## synchronization should be enabled when features for multiple nodes like notification streaming are deployed
synchronization:
    pubsub:
        redis:
            host: "localhost:6379"
            auth_token: ""  # Use auth_token, redis_secret, or password
            database: 0

            ## Optional: Redis Streams tuning (only applies if Redis >= 5.0 detected)
            ## Uncomment to override defaults. Leave commented for recommended defaults.
            # batch_size: 10           # Messages per batch (default: 10)
            # flush_interval: 5s       # Max wait before sending batch (default: 5s)
            # max_retries: 3           # Retry attempts on failure (default: 3)
            # retry_delay: 100ms       # Initial retry delay (default: 100ms)
            # max_retry_delay: 5s      # Max retry delay with backoff (default: 5s)
            # connection_timeout: 10s  # Redis connection timeout (default: 10s)

    ## if notification synchronization is enabled, then the active notification event-stream API
    ## will get the notifications from available replicas
    notification:
        enable: true
        default: "redis"  # Agent auto-detects best option based on Redis version
```

**What happens at startup**

Agent connects to Redis, runs `INFO server` command, and checks Redis version:

- Redis 7.x, 6.x, 5.x → Uses Redis Streams
- Redis 4.x, 3.x, 2.x → Uses Redis Pub/Sub
- Detection fails → Falls back to Redis Pub/Sub (still works, just simpler)

**Log examples**

Redis Streams detected:

```javascript
INFO Auto-detecting Redis version to choose best notification implementation...
INFO Redis Streams supported - will use Streams for notifications redis_version=6
```

Redis Pub/Sub fallback:

```javascript
INFO Auto-detecting Redis version to choose best notification implementation...
INFO Redis Streams not supported - will use Pub/Sub for notifications redis_version=4 min_required=5
```

## Notification sync: Redis Streams and Redis Pub/Sub

Agent automatically chooses between two Redis notification systems based on your Redis version:

| Feature           | Redis Pub/Sub                  | Redis Streams                        |
| ----------------- | ------------------------------ | ------------------------------------ |
| Delivery          | Fire-and-forget                | Persistent with acknowledgment       |
| Message loss      | Possible if subscriber offline | No loss (messages queued)            |
| Consumer groups   | No                             | Yes (load balancing)                 |
| Automatic retries | No                             | Yes (with exponential backoff)       |
| Message batching  | No                             | Yes (configurable)                   |
| Redis version     | 2.0+ required                  | 5.0+ required                        |
| Selection         | Auto-detected (\< 5.0)         | Auto-detected (>= 5.0)               |
| Best for          | Simple, low-traffic setups     | Production, high-traffic deployments |

### Recommendation

Use **Redis 5.0+** for production deployments requiring reliable message delivery. Agent will automatically use Redis Streams for optimal performance.

## How auto-detection works

When Agent starts with `default: "redis"` configured, the following occurs:

1. Connects to Redis using provided host and credentials.
2. Runs version check using `INFO server` command.
3. Parses version (for example, `redis_version:6.2.5`).
4. Chooses implementation
   - Major version >= 5 → Redis Streams.
   - Major version \< 5 → Redis Pub/Sub.
   - Detection fails → Redis Pub/Sub (safe fallback).

**No configuration changes needed when upgrading Redis**

- Upgrade Redis 4.x → 6.x
- Restart Agent
- Automatically switches to Streams (no config change needed!)

## Redis Streams configuration options

Basic setup (recommended for most users)

```yaml
synchronization:
  pubsub:
    redis:
      host: "localhost:6379"
      auth_token: "your-redis-token"
      database: 0

  notification:
    enable: true
    default: "redis"  # Auto-detects and uses Streams if Redis >= 5.0
```

With custom tuning (optional)

If you need to tune performance for your traffic patterns, you can override these defaults:

```yaml
synchronization:
  pubsub:
    redis:
      host: "localhost:6379"
      auth_token: "your-redis-token"
      database: 0

      # All parameters below are OPTIONAL - only set if you need to override defaults
      # These only apply when Agent detects Redis >= 5.0 (Streams mode)
      batch_size: 10           # How many messages to group together (default: 10)
      flush_interval: 5s       # Max time to wait before sending batch (default: 5s)
      max_retries: 3           # Number of retry attempts on failure (default: 3)
      retry_delay: 100ms       # Initial retry wait time (default: 100ms)
      max_retry_delay: 5s      # Maximum retry wait time (default: 5s)
      connection_timeout: 10s  # Redis connection timeout (default: 10s)

  notification:
    enable: true
    default: "redis"
```

:::hint{type="info"}
**Note**
These batching parameters are **ignored** if Agent detects Redis \< 5.0 (Pub/Sub mode). Pub/Sub doesn't support batching.

If using notifications API (/v1/notifications/event-stream), in the **server** section of config.yaml increase these timeouts to prevent SSE disconnects:

`readTimeout: 5s` -> `readTimeout: 300s`  (or appropriate higher value)
`writeTimeout: 10s` -> `writeTimeout: 300s` (or appropriate higher value)
:::

## How batching works (Redis Streams only)

When Agent detects Redis >= 5.0 and uses Streams, it groups notifications into batches for efficiency.

Without batching (Redis Pub/Sub - Redis \< 5.0)

```javascript
Decision 1 → PUBLISH immediately
Decision 2 → PUBLISH immediately
Decision 3 → PUBLISH immediately
```

With batching (Redis Streams - Redis >= 5.0)

```javascript
Decision 1 → Add to batch (wait)
Decision 2 → Add to batch (wait)
Decision 3 → Add to batch (wait)
... 10 decisions collected OR 5 seconds elapsed ...
→ XADD all 10 messages to stream at once
```

:::hint{type="info"}
**Note**
Each message is still stored individually in the stream. Batching only affects the **write operation** to Redis, not the message structure. Subscribers read messages one at a time.
:::

## Notification message structure

When subscribers read from the stream, each notification contains a `type` and `message` payload.

Decision notification (triggered by `/v1/decide`)

```json
{
  "type": "decision",
  "message": {
    "Type": "flag",
    "UserContext": {
      "ID": "user_123",
      "Attributes": {}
    },
    "DecisionInfo": {
      "flagKey": "my_flag",
      "enabled": true,
      "variationKey": "variation_a",
      "ruleKey": "experiment_123",
      "experimentId": "12345",
      "variationId": "67890",
      "variables": {
        "color": "blue",
        "size": "large"
      },
      "reasons": [
        "User \"user_123\" meets audience conditions."
      ]
    }
  }
}
```

**Track notification** (triggered by `/v1/track`)

```json
{
  "type": "track",
  "message": {
    "Type": "track",
    "UserContext": {
      "ID": "user_123",
      "Attributes": {
        "browser": "chrome"
      }
    },
    "EventInfo": {
      "eventKey": "purchase",
      "tags": {
        "revenue": 4200,
        "category": "electronics"
      }
    }
  }
}
```

**Datafile update notification** (triggered by webhook or polling)

```json
{
  "type": "datafile-update",
  "message": {
    "Type": "datafile-update",
    "Revision": "42",
    "ProjectId": "123456789"
  }
}
```

All notification types are synced across Agent instances when Redis is enabled.

## Authentication options

Agent supports flexible Redis authentication field names (to avoid triggering security scanners).

```yaml
redis:
  host: "localhost:6379"
  # Choose ONE of these (in order of priority):
  auth_token: "token123"      # Recommended (highest priority)
  # OR
  redis_secret: "secret456"   # Alternative field name
  # OR
  password: "pass789"         # Legacy field name (still supported)
```

Environment variables (fallback)

- `REDIS_PASSWORD` – General fallback
- `REDIS_PUBSUB_PASSWORD` – Sync-specific

## Requirements

- **Redis Streams (auto-selected)** – Requires Redis 5.0 or later.
- **Redis Pub/Sub (auto-fallback)** – Works with Redis 2.0+.

## Performance tuning guide

:::hint{type="info"}
**Note**
These tuning parameters only apply when Agent detects Redis >= 5.0 (Streams mode).
:::

### Low-latency (quick decisions, low volume)

```yaml
batch_size: 5
flush_interval: 500ms
```

Messages sent faster but more frequent Redis writes.

### High-throughput (many decisions, can tolerate slight delay)

```yaml
batch_size: 100
flush_interval: 5s
```

Fewer Redis writes, better throughput, but notifications delayed up to 5 seconds.

### Balanced (default - recommended for most cases)

```yaml
# Just use defaults - do not specify these parameters.
# batch_size: 10
# flush_interval: 5s
```

## Upgrade Redis version

When you upgrade your Redis server (for example, from Redis 4.x to Redis 6.x), Agent *automatically* switches to using Redis Streams on the next restart.

## Advanced configuration

For detailed information on Redis Streams including monitoring, troubleshooting, and migration from Redis Pub/Sub, see [docs/redis-streams.md](https://github.com/optimizely/agent/blob/master/docs/redis-streams.md) in the Agent GitHub repository.
