Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
28 Aug 2025 · 6 min read ·Article 59 / 125
Go

59 Subscription Schema and Resolver

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

59 Subscription Schema and Resolver: Understanding the Concepts, Practice, and Implementation in GraphQL

When we talk about GraphQL, we cannot separate it from its three main pillars: schema, resolver, and subscription. In this article specifically, I’ll dig deep into subscription schemas and resolvers and why they matter in modern API development.

I’ll assume the reader is already familiar with the basic concepts of queries and mutations in GraphQL. This time we’ll focus on the subscription mechanism, which serves as the bridge between the backend and a real-time frontend. You’ll find explanations, simulations, comparison tables, and even real code examples covering subscriptions in GraphQL.


1. Subscriptions in GraphQL: What Are They and Why Do They Matter?

Before diving into schemas and resolvers, let’s refresh our understanding of subscriptions a bit.

A subscription allows a client to subscribe to specific events and receive data in real time, without having to manually poll the server. This is extremely useful for chat applications, analytics dashboards, notifications, and a wide range of applications built around real-time concepts.

A comparison of the data communication models:

QueryMutationSubscription
NatureRequest/responseWriteStream/push
ResponseOnceOncePeriodic (realtime)
Example use caseFetch a tableDelete dataIncoming chat

2. Subscription Flow Diagram

To make it easier to picture, here is the subscription flow diagram that we’ll implement later, using Mermaid syntax:

MERMAID
sequenceDiagram
    participant Client
    participant Server
    participant PubSub

    Client->>Server: Kirim request subscription
    Server-->>Client: Mendengar event (connection ack)
    PubSub-->>Server: New event published
    Server-->>Client: Kirim data baru via websocket

Here, the Server listens for events from PubSub (the Publish/Subscribe mechanism) and then forwards them to any Client that has an open connection.


3. Declaring a Subscription Schema in GraphQL

The schema in GraphQL defines the shape and types of events that a client can subscribe to.

graphql
 1type Subscription {
 2  messageSent(roomId: ID!): Message
 3}
 4
 5type Message {
 6  id: ID!
 7  content: String!
 8  sender: String!
 9  sentAt: String!
10}

Explanation:

  • The subscription is named messageSent and returns a Message type.
  • The roomId parameter is of type ID — it will only receive messages from a specific room.
  • The Message type describes the shape of the object sent to the client.

4. Resolver: The Bridge Between Schema and Backend

A resolver is the logic code that connects the schema to a data source (whether that’s a database, an event emitter, and so on).

Implementing a subscription differs from a query or mutation. A subscription resolver must return an async iterator so the server can stream data to the client.

We’ll use the popular graphql-subscriptions package, which provides a simple PubSub backed by an internal EventEmitter.

Step 1: Set up PubSub and the Resolver

javascript
 1const { PubSub } = require('graphql-subscriptions');
 2const pubsub = new PubSub();
 3
 4const SUBSCRIPTION_TOPIC = 'MESSAGE_SENT';
 5
 6const resolvers = {
 7  Subscription: {
 8    messageSent: {
 9      subscribe: (_, { roomId }) =>
10        pubsub.asyncIterator(`${SUBSCRIPTION_TOPIC}_${roomId}`),
11    },
12  },
13};

Explanation:

  • When a client subscribes to messageSent, the resolver returns an async iterator for a specific topic (in this case, based on the roomId).

Step 2: Publish an Event When a New Message Arrives

Simulate publishing an event when a new message is sent (for example, via the sendMessage mutation):

javascript
 1const resolvers = {
 2  Mutation: {
 3    sendMessage: async (_, { roomId, content, sender }) => {
 4      const message = { id: Date.now(), content, sender, sentAt: new Date().toISOString() };
 5      // Simulate saving to the DB
 6      // db.saveMessage(message);
 7
 8      // Publish the event to subscribers of the matching topic
 9      await pubsub.publish(`${SUBSCRIPTION_TOPIC}_${roomId}`, {
10        messageSent: message,
11      });
12      return message;
13    },
14  },
15};

5. Simulating the Subscription Flow

Let’s test the process:

Simulation Steps

  1. Client A subscribes to the following subscription:

    graphql
    1subscription {
    2  messageSent(roomId: "room-59") {
    3    id
    4    content
    5    sender
    6    sentAt
    7  }
    8}
  2. Client B sends a message via a mutation:

    graphql
    1mutation {
    2  sendMessage(roomId: "room-59", content: "Halo, GraphQL!", sender: "Budi") {
    3    id
    4    content
    5  }
    6}
  3. Client A receives the new message without any polling. The server automatically pushes the data:

    json
     1{
     2  "data": {
     3    "messageSent": {
     4      "id": "1718717500000",
     5      "content": "Halo, GraphQL!",
     6      "sender": "Budi",
     7      "sentAt": "2024-06-15T19:38:20Z"
     8    }
     9  }
    10}

In practice, you’ll often use WebSocket (for example subscriptions-transport-ws or a package within Apollo Server) as the underlying protocol to achieve true real-time behavior.


6. Case Study: Comparison Table (Query vs Subscription)

FeatureQuerySubscription
MechanismHTTP, statelessWebSocket, stateful connection
When to useData snapshotReal-time event streaming
ScalabilityEasy (caching, CDN)Fairly hard, needs proper infra
Popular use casesReports, statisticsChat, notifications, realtime prices

7. Best Practices & Tips

  • Use Filtering: Always limit the events being sent. Use parameters on the subscription (for example, roomId).
  • Authentication: Make sure only authorized clients can subscribe; filter at the resolver layer.
  • Scalability: Implement tools like Redis PubSub or Kafka once your application reaches a larger scale.
  • Handle Disconnects: Make sure clients can reconnect/re-subscribe if the WebSocket connection drops.

8. End-to-End Implementation Example (Mini Project)

Here is a snippet of a GraphQL server (Node.js + Apollo Server) that runs subscriptions with a local PubSub:

javascript
 1const { ApolloServer, gql } = require('apollo-server');
 2const { PubSub } = require('graphql-subscriptions');
 3const pubsub = new PubSub();
 4
 5const typeDefs = gql`
 6  type Message {
 7    id: ID!
 8    content: String!
 9    sender: String!
10    sentAt: String!
11  }
12
13  type Query {
14    _empty: String
15  }
16
17  type Mutation {
18    sendMessage(roomId: ID!, content: String!, sender: String!): Message!
19  }
20
21  type Subscription {
22    messageSent(roomId: ID!): Message!
23  }
24`;
25
26const SUBSCRIPTION_TOPIC = 'MESSAGE_SENT';
27
28const resolvers = {
29  Mutation: {
30    sendMessage: async (_, { roomId, content, sender }) => {
31      const message = { id: Date.now(), content, sender, sentAt: new Date().toISOString() };
32      await pubsub.publish(`${SUBSCRIPTION_TOPIC}_${roomId}`, {
33        messageSent: message,
34      });
35      return message;
36    },
37  },
38  Subscription: {
39    messageSent: {
40      subscribe: (_, { roomId }) =>
41        pubsub.asyncIterator(`${SUBSCRIPTION_TOPIC}_${roomId}`),
42    },
43  },
44};
45
46const server = new ApolloServer({ typeDefs, resolvers });
47
48server.listen().then(({ url, subscriptionsUrl }) => {
49  console.log(`🚀 Server ready at ${url}`);
50  console.log(`🚀 Subscriptions ready at ${subscriptionsUrl}`);
51});

9. Conclusion: Subscription = The Future of the Real-Time Web

By understanding subscription schemas and resolvers, we can build real-time features that are efficient, clean, and maintainable. GraphQL subscriptions offer an ideal solution in an era of increasingly interactive and responsive applications.

The main challenge lies in scalability and connection management, but with the right architecture and best practices, subscriptions can become a go-to weapon for the modern backend.

Interested in trying it in your own project? Let’s subscribe to the future! 🚀

Related Articles

💬 Comments