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

# Realtime

> Subscribe to real-time data changes via Server-Sent Events

The Realtime API allows you to subscribe to real-time updates for record changes using Server-Sent Events (SSE).

## Connect to realtime

Establish a realtime SSE connection.

```bash theme={null}
GET /api/realtime
```

**Authentication:** Optional (unauthenticated connections are guests)

This endpoint establishes a persistent SSE connection that remains open to receive real-time messages.

### Response

The connection returns Server-Sent Events in the following format:

```
id: clientId
event: PB_CONNECT
data: {"clientId":"client_id_here"}

event: subscription_name
data: {"action":"create","record":{...}}
```

<ResponseField name="clientId" type="string">
  Unique client connection identifier returned in the initial `PB_CONNECT` event
</ResponseField>

<CodeGroup>
  ```javascript JavaScript theme={null}
  const eventSource = new EventSource('http://127.0.0.1:8090/api/realtime');

  eventSource.addEventListener('PB_CONNECT', (e) => {
    console.log('Connected:', e.data);
  });

  eventSource.addEventListener('posts', (e) => {
    const data = JSON.parse(e.data);
    console.log('Record change:', data.action, data.record);
  });
  ```

  ```bash curl theme={null}
  curl -N http://127.0.0.1:8090/api/realtime
  ```
</CodeGroup>

## Set subscriptions

Subscribe to specific topics to receive real-time updates.

```bash theme={null}
POST /api/realtime
```

**Authentication:** Optional (but required to upgrade guest connection to authenticated)

### Request body

<ParamField body="clientId" type="string" required>
  The client ID from the initial connection (returned in `PB_CONNECT`)
</ParamField>

<ParamField body="subscriptions" type="array" required>
  Array of subscription topics (max 1000 subscriptions, each max 2500 chars)
</ParamField>

### Subscription topics

You can subscribe to:

**Individual record:**

```
{collection}/{recordId}
```

**All records in collection:**

```
{collection}/*
```

**Collection name or ID:**

```
posts/*
collection_id/*
```

**With filters and options:**
Append query parameters to subscription topics:

```
posts/*?filter=status='published'&expand=author&fields=id,title
```

<CodeGroup>
  ```bash Subscribe to collection theme={null}
  curl -X POST http://127.0.0.1:8090/api/realtime \
    -H "Content-Type: application/json" \
    -d '{
      "clientId": "client_id_from_connect",
      "subscriptions": ["posts/*", "users/*"]
    }'
  ```

  ```bash With filters theme={null}
  curl -X POST http://127.0.0.1:8090/api/realtime \
    -H "Content-Type: application/json" \
    -d '{
      "clientId": "client_id_from_connect",
      "subscriptions": ["posts/*?filter=status='published'"]
    }'
  ```

  ```bash Specific record theme={null}
  curl -X POST http://127.0.0.1:8090/api/realtime \
    -H "Content-Type: application/json" \
    -d '{
      "clientId": "client_id_from_connect",
      "subscriptions": ["posts/RECORD_ID"]
    }'
  ```
</CodeGroup>

### Response

Returns 204 No Content on success.

## Realtime events

When subscribed, you'll receive events when records change:

### Event structure

<ResponseField name="action" type="string">
  The type of change: `create`, `update`, or `delete`
</ResponseField>

<ResponseField name="record" type="object">
  The affected record data (respects API rules and field permissions)
</ResponseField>

### Example event

```json theme={null}
{
  "action": "create",
  "record": {
    "id": "RECORD_ID",
    "collectionId": "collection_id",
    "collectionName": "posts",
    "created": "2023-01-01 00:00:00.000Z",
    "updated": "2023-01-01 00:00:00.000Z",
    "title": "New post",
    "content": "Post content"
  }
}
```

## Client-side subscriptions

### JavaScript example

```javascript theme={null}
let clientId = '';
const eventSource = new EventSource('http://127.0.0.1:8090/api/realtime');

// Handle connection
eventSource.addEventListener('PB_CONNECT', async (e) => {
  const data = JSON.parse(e.data);
  clientId = data.clientId;
  
  // Subscribe to topics
  await fetch('http://127.0.0.1:8090/api/realtime', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      clientId: clientId,
      subscriptions: ['posts/*', 'comments/*']
    })
  });
});

// Handle record changes
eventSource.addEventListener('posts/*', (e) => {
  const data = JSON.parse(e.data);
  
  switch (data.action) {
    case 'create':
      console.log('New post:', data.record);
      break;
    case 'update':
      console.log('Updated post:', data.record);
      break;
    case 'delete':
      console.log('Deleted post:', data.record);
      break;
  }
});

// Handle errors
eventSource.onerror = (error) => {
  console.error('SSE error:', error);
  eventSource.close();
};
```

## Access control

Realtime subscriptions respect collection API rules:

* **listRule** - For wildcard subscriptions (`posts/*`)
* **viewRule** - For specific record subscriptions (`posts/RECORD_ID`)

<Note>
  Users only receive updates for records they have permission to view based on the collection's API rules.
</Note>

### Authentication state

You can upgrade a guest connection to authenticated:

1. Establish SSE connection (guest)
2. Make POST request to `/api/realtime` with auth token
3. Subscription permissions are updated based on the auth record

<Warning>
  You cannot change authentication from one user to another. Downgrading from authenticated to guest is also not allowed.
</Warning>

## Subscription options

Add query parameters to subscription topics:

### Filter

Only receive events for records matching the filter:

```
posts/*?filter=status='published' && author=@request.auth.id
```

### Expand

Automatically expand relation fields:

```
posts/*?expand=author,categories
```

### Fields

Limit fields included in the event:

```
posts/*?fields=id,title,created
```

### Combined options

```
posts/*?filter=featured=true&expand=author&fields=id,title,author
```

## Connection management

### Idle timeout

Connections automatically close after 5 minutes of inactivity (no events sent). The client should reconnect and resubscribe.

### Reconnection

When the connection drops:

1. Establish a new realtime connection
2. Get new `clientId` from `PB_CONNECT` event
3. Resubmit all subscriptions

```javascript theme={null}
eventSource.onerror = () => {
  eventSource.close();
  // Wait a bit before reconnecting
  setTimeout(() => {
    connectToRealtime();
  }, 1000);
};
```

### Unsubscribing

To change subscriptions, send a new subscription list. Previous subscriptions are automatically cleared:

```bash theme={null}
curl -X POST http://127.0.0.1:8090/api/realtime \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "client_id",
    "subscriptions": []  # Empty array unsubscribes from all
  }'
```

## Performance considerations

<Note>
  * Maximum 1000 subscriptions per client
  * Each subscription topic max 2500 characters
  * Realtime events are processed in chunks of 150 clients
</Note>

### Best practices

1. Subscribe to specific collections rather than all records
2. Use filters to reduce event volume
3. Limit fields to only what you need
4. Close connections when not needed
5. Implement reconnection logic

## Common use cases

### Chat application

```javascript theme={null}
subscriptions: [
  'messages/*?filter=room="' + roomId + '"&sort=-created'
]
```

### User notifications

```javascript theme={null}
subscriptions: [
  'notifications/*?filter=user="' + userId + '" && read=false'
]
```

### Live dashboard

```javascript theme={null}
subscriptions: [
  'orders/*?filter=status="pending"',
  'users/*?filter=created>' + today
]
```

### Collaborative editing

```javascript theme={null}
subscriptions: [
  'documents/' + documentId,
  'comments/*?filter=document="' + documentId + '"'
]
```
