docs/1.0/04-Reference/02-Prisma-API/05-Subscriptions.md
GraphQL subscriptions allow you to be notified in realtime when changes are happening to your data. There are three kinds of events that trigger a subscription:
This is an example subscription that notifies you whenever a new Post node is created. When the subscription fires, the payload that's sent by the server will contain the description and imageUrl of the Post:
subscription newPosts {
post(where: {
mutation_in: [CREATED]
}) {
mutation
node {
description
imageUrl
}
}
}
Subscriptions use a special websocket endpoint.
Here's a list of available subscriptions. To explore them, use the GraphQL Playground inside your service.
You can combine multiple subscription triggers within a single subscription request to control exactly what events you want to be notified of. The subscriptions API also uses the rich fitler system that's available for queries.
When using Apollo Client, you can use the apollo-link-ws library to facilite subscription use. Here's an example.
You can also use the GraphQL Playground or any WebSocket client as described below.
A GraphQL Playground can be used to explore and run GraphQL subscriptions.
Subscriptions are managed through WebSockets. First establish a WebSocket connection and specify the graphql-subscriptions protocol:
let webSocket = new WebSocket('wss://__CLUSTER__.prisma.sh/__WORKSPACE__/__SERVICE__/__STAGE__', 'graphql-subscriptions');
Next you need to initiate a handshake with the WebSocket server. You do this by listening to the open event and then sending a JSON message to the server with the type property set to init:
webSocket.onopen = (event) => {
const message = {
type: 'init'
}
webSocket.send(JSON.stringify(message))
}
The server may respond with a variety of messages distinguished by their type property. You can react to each message as appropriate for your application:
webSocket.onmessage = (event) => {
const data = JSON.parse(event.data)
switch (data.type) {
case 'init_success': {
console.log('init_success, the handshake is complete')
break
}
case 'init_fail': {
throw {
message: 'init_fail returned from WebSocket server',
data
}
}
case 'subscription_data': {
console.log('subscription data has been received', data)
break
}
case 'subscription_success': {
console.log('subscription_success')
break
}
case 'subscription_fail': {
throw {
message: 'subscription_fail returned from WebSocket server',
data
}
}
}
}
To subscribe to data changes, send a message with the type property set to subscription_start:
const message = {
id: '1',
type: 'subscription_start',
query: `
subscription newPosts {
post(filter: {
mutation_in: [CREATED]
}) {
mutation
node {
description
imageUrl
}
}
}
`
}
webSocket.send(JSON.stringify(message))
You should receive a message with type set to subscription_success. When data changes occur, you will receive messages with type set to subscription_data. The id property that you supply in the subscription_start message will appear on all subscription_data messages, allowing you to multiplex your WebSocket connection.
To unsubscribe from data changes, send a message with the type property set to subscription_end:
const message = {
id: '1',
type: 'subscription_end'
}
webSocket.send(JSON.stringify(message))
For every available object type in your data model, certain subscriptions are automatically generated.
As an example, consider the following data model with a single Post type:
type Post {
id: ID! @unique
title: String!
description: String
}
In the gerated Prisma API, a post subscription will be available that you can use to be notified whenever certain nodes of type Post are created, updated or deleted.
For a given type, you can subscribe to all nodes that are being created using the generated type subscription.
If you want to subscribe to created nodes of the Post type, you can use the Post subscription and specify the where object and set mutation_in: [CREATED].
subscription {
post(where: {
mutation_in: [CREATED]
}) {
mutation
node {
description
imageUrl
author {
id
}
}
}
}
The payload contains:
mutation: In this case it will return CREATED.node: Allows you to query information on the created node (and potentially its related nodes).You can make use of a similar filter system as for queries using the node argument of the where object.
For example, to only be notified of a created Post if a specific user follows the author:
subscription {
post(where: {
mutation_in: [CREATED]
node: {
author: {
followedBy_some: {
id: "cj03x3nacox6m0119755kmcm3"
}
}
}
}) {
mutation
node {
description
imageUrl
author {
id
}
}
}
}
For a given type, you can subscribe to all nodes that are being deleted using the generated type subscription.
If you want to subscribe for updated nodes of the Post type, you can use the Post subscription and specify the where object and set mutation_in: [DELETED].
subscription deletePost {
post(where: {
mutation_in: [DELETED]
}) {
mutation
previousValues {
id
}
}
}
The payload contains
mutation: In this case it will return DELETED.previousValues: Previous scalar values of the node.Note:
previousValuesis alwaysnullforCREATEDsubscriptions.
You can make use of a similar filter system as for queries using the node argument of the where object.
For example, to only be notified of a deleted Post if a specific user follows the author:
subscription {
post(where: {
mutation_in: [DELETED]
node: {
author: {
followedBy_some: {
id: "cj03x3nacox6m0119755kmcm3"
}
}
}
}) {
mutation
previousValues {
id
}
}
}
For a given type, you can subscribe to all nodes being updated using the generated type subscription.
If you want to subscribe to updated nodes of the Post type, you can use the Post subscription and specify the where object and set mutation_in: [UPDATED].
subscription {
post(where: {
mutation_in: [UPDATED]
}) {
mutation
node {
description
imageUrl
author {
id
}
}
updatedFields
previousValues {
description
imageUrl
}
}
}
The payload contains
mutation: In this case it will return UPDATED.node: Allows you to query information on the updated node and connected nodes.updatedFields: A list of the fields that changed.previousValues: Previous scalar values of the node.Note:
updatedFieldsis alwaysnullforCREATEDandDELETEDsubscriptions.previousValuesis alwaysnullforCREATEDsubscriptions.
You can make use of a similar filter system as for queries using the node argument of the where object.
For example, to only be notified of an updated Post if its description changed:
subscription {
post(where: {
mutation_in: [UPDATED]
updatedFields_contains: "description"
}) {
mutation
node {
description
}
updatedFields
previousValues {
description
}
}
}
Similarily to updatedFields_contains, more filter conditions exist:
updatedFields_contains_every: [String!]: Matches if all fields specified have been updated.updatedFields_contains_some: [String!]: Matches if some of the specified fields have been updated.Note: You cannot use the
updatedFieldsfilter conditions together withmutation_in: [CREATED]ormutation_in: [DELETED]!
Currently, subscriptions for relation updates are only available with a workaround using UPDATED subscriptions.
You can force a notification changes by touching nodes. Add a dummy: String field to the type in question and update this field for the node whose relation status just changed.
mutation updatePost {
updatePost(
where: {
id: "some-id"
}
data: {
dummy: "dummy" # do a dummy change to trigger update subscription
}
)
}
If you're interested in a direct relation trigger for subscriptions, please join the discussion on GitHub.
You can subscribe to multiple mutations on the same type in one subscription.
Using the mutation_in argument of the where object, you can select the type of mutation that you want to subscribe to. For example, to subscribe to the createPost, updatePost and deletePost mutations:
subscription {
post(where: {
mutation_in: [CREATED, UPDATED, DELETED]
}) {
mutation
node {
id
description
}
updatedFields
previousValues {
description
imageUrl
}
}
}
To select specific nodes that you want to be notified about, use the node argument of the where object. You can combine it with mutation_in. For example, to only be notified of created, updated and deleted posts if a specific user follows the author:
subscription {
post(
where: {
mutation_in: [CREATED, UPDATED, DELETED]
}
node: {
author: {
followedBy_some: {
id: "cj03x3nacox6m0119755kmcm3"
}
}
}
) {
mutation
node {
id
description
}
updatedFields
previousValues {
description
imageUrl
}
}
}
Note:
previousValuesis alwaysnullforCREATEDsubscriptions andupdatedFieldsis alwaysnullforCREATEDandDELETEDsubscriptions.
You can make use of a similar filter system as for queries using the where argument.
For example, you can subscribe to all CREATED and DELETE subscriptions, as well as all UPDATED subscriptions when the imageUrl was updated:
subscription {
post(where: {
OR: [{
mutation_in: [CREATED, DELETED]
}, {
mutation_in: [UPDATED]
updatedFields_contains: "imageUrl"
}]
}) {
mutation
node {
id
description
}
updatedFields
previousValues {
description
imageUrl
}
}
}
Note: Using any of the
updatedFieldsfilter conditions together withCREATEDorDELETEDsubscriptions results in an error.previousValuesis alwaysnullforCREATEDsubscriptions andupdatedFieldsis alwaysnullforCREATEDandDELETEDsubscriptions.