# Subscriptions

> Learn to manage realtime subscriptions with both websockets and GraphQL.

WebSocket subscriptions allow for real-time notification of item creations, edits, and deletions in a collection.

## Subscribe to Changes in a Collection

Send the following message over your WebSocket connection to start a subscription:

```json
{
    "type": "subscribe",
    "collection": "messages"
}
```

In return, you will receive a message to confirm that your subscription has been initialized:

```json
{
    "type": "subscription",
    "event": "init"
}
```

## Handling Collection Changes

When a change happens to an item in a collection with an active subscription, it will emit a message.

```json
{
    "type": "subscription",
    "event": "create",
    "data": [
        // ...
    ]
}
```

The `event` will be one of `create`, `update`, or `delete`. If the event is `create` or `update`, the `data` will
contain the full item objects (or specific fields, if specified). If the event is `delete`, just the `id` will be
returned.

## Working with Specific CRUD Actions

Using the optional `event` argument you can filter for specific `create`, `update`, and `delete` events.

Here's an example of how to do this:

```json
{
    "type": "subscribe",
    "collection": "messages",
    "event": "create"
}
```

## Specifying Fields to Return

If you only want to return specific fields on subscription events, add the `query.fields` property when initializing the
subscription:

```json
{
    "type": "subscribe",
    "collection": "messages",
    "query": { "fields": ["text"] }
}
```

## Using UIDs

The `uid` property serves as a unique identifier included in the message payload. When multiple subscriptions are added to the same collection, the `uid` helps to distinguish the responses of these subscriptions watching different filters or events. A unique identifier will be generated on the server if not explicitly provided when subscribing.

<callout color="warning" icon="i-lucide-triangle-alert">

When manually setting the `uid` property its value needs to be unique per WebSocket connection. Any subsequent duplicate `uid` subscriptions will be ignored.

</callout>

```json
{
    "type": "subscribe",
    "collection": "messages",
    "uid": "any-string-value"
}
```

When you receive responses, the same `uid` will be included as a property:

```json
{
    "type": "subscription",
    "event": "create",
    "data": [
        // ...
    ],
    "uid": "any-string-value"
}
```

## Unsubscribing from Changes

To stop change events being sent from a specific subscription, send the following message:

```json
{
    "type": "unsubscribe",
    "uid": "identifier"
}
```

You can also omit `uid` to stop all subscriptions at once.

## GraphQL Subscriptions

GraphQL subscriptions provide live updates that are delivered in real-time whenever an item is created, updated or
deleted in your collection.

Establish a WebSocket connection between the client and server using `createClient` from `graphql-ws`. To authenticate,
enter both `your-directus-url` and the generated `token`.

```js
import { createClient } from "graphql-ws";

const client = createClient({
    url: "ws://your-directus-url/graphql",
    keepAlive: 30000,
    connectionParams: async () => {
        return { access_token: "MY_TOKEN" };
    },
});
```

This creates a connection and ensures that only authorized clients can access the resources and real-time
data updates.

### Subscribe to Changes in a Collection

Send the following query, `<collection>_mutated` over your WebSocket connection to subscribe to changes. If you want to
subscribe to a `posts` collection, the query would look like this:

```graphql
subscription {
    posts_mutated {
        key
        event
        data {
            id
            text
        }
    }
}
```

In return, this query will subscribe to changes in the posts collection and return the `id` and `text` fields of the
post added.

## Handling Collection Changes

When a change happens to an item in a collection with an active subscription, it will emit a post.

```json
{
    "posts_mutated": {
        "key": "1",
        "event": "create",
        "data": {
            "id": "1",
            "text": "Hello world!"
        }
    }
}
```

An event will be either `create`, `update`, or `delete`. If the event is `create` or `update`, the payload will contain
the full item objects (or specific fields, if specified). If the event is `delete`, just the `key` will be filled the
other requested fields will be `null`.

## Working with Specific CRUD Operations

Using the `event` argument you can filter for specific `create`, `update`, and `delete` events. Here's an example of how
to do this:

```graphql
subscription {
    posts_mutated(event: create) {
        key
        data {
            text
        }
    }
}
```

## Pings To Keep Connection Active

You will periodically receive a message with a type of `ping`. This serves two purposes:

1. To act as a periodic message to stop your connection from closing due to inactivity. This may be required by your application technology stack.
2. To verify that the connection is still active.

In order to prevent the connection from *closing*, you may reply with a `pong` event:

```js
connection.addEventListener('message', (message) => {
    const data = JSON.parse(message.data);

    if (data.type === 'ping') {
        this.connection.send(
            JSON.stringify({
                type: 'pong',
            }),
        );
    }
});
```

On Directus Cloud, this feature is enabled. If you are self-hosting, you can alter this behavior with the `WEBSOCKETS_HEARTBEAT_ENABLED` and `WEBSOCKETS_HEARTBEAT_PERIOD` environment variables.

You may wish to exclude these messages from your application logic.

## Unsubscribing from Changes

To unsubscribe from a subscription, use the `dispose` method. Here's an example:

```js
client.dispose();
```

Calling `dispose` sends a post to the server to unsubscribe from the specified subscription. This will stop receiving
any further updates for that subscription.
