Home

Realtime Protocol

The Realtime Protocol is a set of message formats used for communication over a WebSocket connection between a Realtime client and server. These messages are used to initiate a connection, update access tokens, receive system status updates, and receive real-time updates from the Postgres database.

Connection#

In the initial message, the client sends a message specifying the features they want to use (Broadcast, Presence, Postgres Changes).


_23
{
_23
"event": "phx_join",
_23
"topic": string,
_23
"payload": {
_23
"config": {
_23
"broadcast": {
_23
"self": boolean
_23
},
_23
"presence": {
_23
"key": string
_23
},
_23
"postgres_changes": [
_23
{
_23
"event": "*" | "INSERT" | "UPDATE" | "DELETE",
_23
"schema": string,
_23
"table": string,
_23
"filter": string + '=' + "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" + '.' + string
_23
}
_23
]
_23
}
_23
},
_23
"ref": string
_23
}

In response, the server sends the Postgres configuration with a unique ID. With this ID, the client should route incoming changes to the appropriate callback.


_19
{
_19
"event": "phx_reply",
_19
"topic": string,
_19
"payload": {
_19
"response": {
_19
"postgres_changes": [
_19
{
_19
"id": number,
_19
"event": "*" | "INSERT" | "UPDATE" | "DELETE",
_19
"schema": string,
_19
"table": string,
_19
"filter": string + '=' + "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" + '.' + string
_19
}
_19
]
_19
},
_19
"status": "ok" | "error"
_19
},
_19
"ref": string
_19
}

System messages#

System message are used to inform a client about the status of the Postgres subscription. The payload.status indicates if the subscription successful or not. The body of the payload.message can be "Subscribed to PostgreSQL" or "Subscribing to PostgreSQL failed" with subscription params.


_11
{
_11
"event": "system",
_11
"topic": string,
_11
"payload":{
_11
"channel": string,
_11
"extension": "postgres_changes",
_11
"message": "Subscribed to PostgreSQL" | "Subscribing to PostgreSQL failed",
_11
"status": "ok" | "error"
_11
},
_11
"ref": null,
_11
}

Heartbeat#

The heartbeat message should be sent every 30 seconds to avoid a connection timeout.


_10
{
_10
"event": "heartbeat",
_10
"topic": "phoenix",
_10
"payload": {},
_10
"ref": string
_10
}

Access token#

To update the access token, you need to send to the server a message specifying a new token in the payload.access_token value.


_10
{
_10
"event": "access_token",
_10
"topic": string,
_10
"payload":{
_10
"access_token": string
_10
},
_10
"ref": string
_10
}

Postgres CDC message#

Realtime sends a message with the following structure


_18
{
_18
"event": "postgres_changes",
_18
"topic": string,
_18
"payload": {
_18
"data": {
_18
"columns": Array<{name: string, type: string}>,
_18
"commit_timestamp": string,
_18
"errors": null | string,
_18
"old_record": {"id": number | string},
_18
"record": {[key: string]: boolean | number | string | null},
_18
"type": "*" | "INSERT" | "UPDATE" | "DELETE",
_18
"schema": string,
_18
"table": string
_18
},
_18
"ids": Array<number>
_18
},
_18
"ref": null
_18
}

Broadcast message#

Structure of the broadcast event


_10
{
_10
"event": "broadcast",
_10
"topic": string,
_10
"payload": {
_10
"event": string,
_10
"payload": {[key: string]: boolean | number | string | null | undefined},
_10
"type": "broadcast"
_10
},
_10
"ref": null
_10
}

Presence message#

The Presence events allow clients to monitor the online status of other clients in real-time.

State update#

After joining, the server sends a presence_state message to a client with presence information. The payload field contains keys in UUID format, where each key represents a client and its value is a JSON object containing information about that client.


_10
{
_10
"event": "presence_state",
_10
"topic": string,
_10
"payload": {
_10
[key: string]: {metas: Array<{phx_ref: string, name: string, t: float}>}
_10
},
_10
"ref": null
_10
}

Diff update#

After a change to the presence state, such as a client joining or leaving, the server sends a presence_diff message to update the client's view of the presence state. The payload field contains two keys, joins and leaves, which represent clients that have joined and left, respectively. The values associated with each key are UUIDs of the clients.


_10
{
_10
"event": "presence_diff",
_10
"topic": string,
_10
"payload": {
_10
"joins": {metas: Array<{phx_ref: string, name: string, t: float}>},
_10
"leaves": {metas: Array<{phx_ref: string, name: string, t: float}>}
_10
},
_10
"ref": null
_10
}