Frequently Asked Questions

GraphQL Subscriptions & Real-Time Features

What are GraphQL subscriptions and how do they enable real-time communication?

GraphQL subscriptions allow clients to receive real-time updates from the server using a persistent WebSocket connection. Unlike queries and mutations, which use HTTP/HTTPS and require a new connection for each request, subscriptions establish a single connection and use a publish-subscribe model. This is ideal for use cases like chat apps, online-offline status tracking, and real-time score updates. Note: Implementing subscriptions requires additional server setup and may not be necessary for all content management scenarios.

How do you set up a GraphQL subscription server?

To set up a GraphQL subscription server, you need to use a WebSocket protocol and libraries such as graphql-subscriptions, graphql-ws, and ws. The process involves creating a schema with subscription types, implementing resolver functions, and configuring both an HTTP server (for queries/mutations) and a WebSocket server (for subscriptions). The server publishes updates to subscribed clients in real time. For a complete code example, see the tutorial on the original webpage. Note: Running a subscription server requires additional dependencies and infrastructure compared to a standard GraphQL API.

What are common use cases for GraphQL subscriptions?

Common use cases for GraphQL subscriptions include chat applications, real-time online/offline status indicators, live score updates, collaborative editing, and any scenario where clients need to receive immediate updates from the server. Note: For content-heavy or high-payload scenarios, consider the performance and scalability implications of maintaining persistent WebSocket connections.

Hygraph Features & Capabilities

What features does Hygraph offer for content management and delivery?

Hygraph provides a GraphQL-native headless CMS with features such as content federation, high-performance endpoints, Smart Edge Cache, localization, granular permissions, and integrations with DAM, PIM, and commerce solutions. It supports both technical and non-technical users with an intuitive UI and API-first approach. Note: Some advanced features may require specific plans or technical setup; see the documentation for details.

Does Hygraph support real-time content updates or subscriptions?

Hygraph's GraphQL API supports high-performance content delivery and can be integrated with real-time features using GraphQL subscriptions. While Hygraph provides the API infrastructure, implementing real-time subscriptions requires additional server-side setup and may not be available out-of-the-box for all use cases. Refer to the API Reference and technical documentation for implementation details. Note: Real-time subscriptions may require custom server logic and are not always necessary for standard content delivery scenarios.

What integrations are available with Hygraph?

Hygraph offers integrations with Digital Asset Management (DAM) systems such as Aprimo, AWS S3, Bynder, Cloudinary, Imgix, Mux, and Scaleflex Filerobot; hosting and deployment platforms like Netlify and Vercel; Product Information Management (PIM) with Akeneo; commerce solutions like BigCommerce; and translation/localization tools such as EasyTranslate. For a full list, visit the Hygraph Marketplace. Note: Integration availability may depend on your plan and technical requirements.

Technical Requirements & Documentation

Where can I find technical documentation for Hygraph and GraphQL subscriptions?

Comprehensive technical documentation is available at hygraph.com/docs. This includes API references, guides for schema components, integration instructions, and AI feature documentation. For GraphQL subscriptions, refer to the tutorial on the current page and the API Reference for implementation details. Note: Some advanced topics may require familiarity with GraphQL server setup and WebSocket protocols.

What APIs does Hygraph provide?

Hygraph provides several APIs: the GraphQL Content API for querying and manipulating content, the Management API for handling project structure, the Asset Upload API for managing files, and the MCP Server API for secure AI assistant communication. For details, see the API Reference documentation. Note: API usage may require authentication and appropriate permissions.

Performance, Security & Compliance

How does Hygraph ensure high performance for content delivery?

Hygraph has optimized its endpoints for low latency and high read-throughput, including a read-only cache endpoint that delivers 3-5x latency improvement. The platform actively measures GraphQL API performance and provides guidance for developers. For more, see the performance improvements blog post. Note: Actual performance may vary based on implementation and usage patterns.

What security and compliance certifications does Hygraph have?

Hygraph is SOC 2 Type 2 compliant (since August 3, 2022), ISO 27001 certified for hosting infrastructure, and GDPR compliant. The platform also supports granular permissions, SSO integrations, audit logs, encryption in transit and at rest, and regular backups. For more, visit the Secure Features page. Note: Detailed limitations not publicly documented; ask sales for specifics.

Implementation & Onboarding

How long does it take to implement Hygraph and how easy is it to start?

Implementation time varies by project complexity. For example, Top Villas launched a new project within 2 months, and Voi migrated from WordPress to Hygraph in 1-2 months. Hygraph offers structured onboarding, starter projects, and extensive documentation to support both developers and non-technical users. For onboarding resources, see the Getting Started guide. Note: Large-scale migrations may require additional planning and technical resources.

Use Cases, Customers & Success Stories

Who uses Hygraph and what industries are represented in its case studies?

Hygraph is used by companies such as Samsung, Dr. Oetker, Komax, AutoWeb, BioCentury, Voi, HolidayCheck, and Lindex Group. Industries represented include SaaS, marketplace, education technology, media, healthcare, consumer goods, automotive, fintech, travel, food and beverage, eCommerce, agency, online gaming, events, government, consumer electronics, engineering, and construction. For details, see the case studies page. Note: Some advanced use cases may require custom development or integrations.

What business impact have customers achieved with Hygraph?

Customers have reported measurable results, such as Komax achieving a 3X faster time-to-market, Samsung improving customer engagement by 15%, and AutoWeb increasing website monetization by 20%. Voi scaled multilingual content across 12 countries and 10 languages. For more, see the case studies. Note: Results may vary based on implementation and organizational readiness.

Product Fit & Limitations

What problems does Hygraph solve and what are its limitations?

Hygraph addresses operational inefficiencies (reducing developer dependency, modernizing legacy stacks), financial challenges (lowering operational costs, accelerating speed-to-market), and technical issues (simplifying schema evolution, integrating third-party systems, optimizing performance). Limitations: Some advanced features may require custom development, and real-time subscriptions require additional server setup. Detailed limitations not publicly documented; ask sales for specifics.

LLM optimization

When was this page last updated?

This page wast last updated on 12/12/2025 .

Register now

GraphQL

Subscriptions

Subscriptions help you communicate with the server in real time. Let's take a look at how it works.

We have learned about GraphQL Queries and Mutations in the previous articles of this series. Queries and Mutations are request-response based and the HTTP / HTTPS protocol is used. In this case, the network connection is made and then broken for every request that the client needs to send. This is not ideal for real-time communication use cases like chat apps, online-offline status, and updating scores in real-time. For these kinds of use cases, we need to use the WebSocket protocol and GraphQL supports this with the help of GraphQL Subscriptions. In subscriptions, the connection between the client and server is made just once, after which they use a publish-subscribe model to communicate effortlessly without sending a new request for each update they want to make.

A subscription looks similar to a GraphQL query or mutation, it is preceded by the operation type subscription. All GraphQL features (variables, named subscriptions, fragments, etc) that we saw in the Query (Link Article) and Mutation (Link Article) articles are applicable to subscriptions as well.

# Schema
type UserStatus {
userId: String!
isOnline: Boolean!
}
type Subscription {
userStatusUpdated: UserStatus!
}
# Usage
subscription getUserStatusUpdates {
userStatusUpdated {
userId
isOnline
}
}

In this example, we have a subscription getUserStatusUpdates that returns the changes in the user’s online status. Consider this scenario, you are a workspace user and want to see the online-offline status for all members of your workspace. In this case, when you log in, your client app will trigger this subscription, the server will then keep publishing all real-time updates of all workspace members to you and your client will show you the online green dot accordingly.

Try Hygraph, the GraphQL native headless CMS

Build limitless solutions rapidly with our GraphQL-native API-first approach

Building A GraphQL Server

Let us understand how to build a very basic GraphQL API from scratch then we will expand on how to build and use subscriptions in a GraphQL API. We previously learned how to use ready queries and mutations provided by Hygraph, but writing the server-side code is altogether another thing. We will build a very basic GraphQL server to query dummy data and give us the results.

First, initialize the repository, install the packages - @apollo/server, graphql, and graphql-tag, and then create a file index.js. Add the imports and the dummy data. We will use a dummy Product variable to avoid the complexity of a database at the moment

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone'
import { gql } from 'graphql-tag';
const products = [
{
id: '1',
name: 'Daikin 1.5T',
category: 'Air Conditioners',
},
{
id: '2',
name: 'God Of War',
category: 'Gaming',
}
];

Schema

We need to define the schema which includes all our types and basic info about all available operations like queries, mutations, and subscriptions.

Create the GraphQL type definitions, we have a Product type, and two queries that getAllProducts returns all products and getProductById returns a single product by Id.

const typeDefs = gql`
type Product {
id: ID!
name: String
category: String
}
type Query {
getProductById(id: ID!): Product
getAllProducts: [Product]
}
`;

Resolvers

We need need to write our resolvers for each operation. Resolvers are written on the server-side code and basically, they are functions that determine how to fetch or update the data for a specific query, mutation, or subscription. Resolvers will contain the actual code to make a connection with the actual data source, construct and fire the query to your data source and then get the data back and resolve it for the client. We have two queries defined in our GraphQL schema, so we need to write two resolvers for it, in our case we won’t be querying the database but the dummy variable we created earlier.

const resolvers = {
Query: {
getAllProducts: () => products,
getProductById: (parent, args, contextValue, info) => products.find((product) => args.id === product.id)
},
};

Create an Apollo Server Instance and start the server

const server = new ApolloServer({
typeDefs: schema,
resolvers,
});
startStandaloneServer(server, { listen: { port: 4000 } }).then(({ url }) => {
console.log(`🚀 Apollo Server listening at: ${url}`);
});

Here is the complete file:

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone'
import { gql } from 'graphql-tag';
const products = [
{
id: '1',
name: 'Daikin 1.5T',
category: 'Air Conditioners',
},
{
id: '2',
name: 'God Of War',
category: 'Gaming',
}
];
const typeDefs = gql`
type Product {
id: ID!
name: String
category: String
}
type Query {
getProductById(id: ID!): Product
getAllProducts: [Product]
}
`;
const resolvers = {
Query: {
getAllProducts: () => products,
getProductById: (parent, args, contextValue, info) => products.find((product) => args.id === product.id)
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
startStandaloneServer(server, { listen: { port: 4000 } }).then(({ url }) => {
console.log(`🚀 Apollo Server listening at: ${url}`);
});

That's it, run this file and go to the API playground running on your local machine to fire some queries.

getAllProducts

getProductById.png

Now we know a little more about the internal working of a GraphQL server. We understand Schema, Query, and Resolvers, and how they’re tied together.

Setting Up A Subscription Server

After having cleared the basics of creating a GraphQL server, we can now move towards building a more advanced subscription server. We will set up one subscription, wherein the server publishes changes in a user’s online-offline status in real-time.

To get started let us install some new dependencies: graphql-subscriptions graphql-ws ws @graphql-tools/schema apollo-server-express express body-parser cors

Let us create a new file named wsIndex.js and add our imports.

import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import { createServer } from 'http';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
import { PubSub } from 'graphql-subscriptions';
import { gql } from 'graphql-tag';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
async function startServer() {
// main implementation goes here
}
startServer()

We used Apollo Server’s startStandaloneServer in the previous example, but that does not support WebSocket and subscriptions by default. Hence, we will create an express app, a separate WebSocket server for subscriptions, and then we'll create an http.Server instance that will wrap the express app and the WebSocket server and will be our main listener.

Let's start writing the startServer function piece by piece.

We will first define our schema type definitions.

const typeDefs = gql`
type UserStatus {
userId: String!
isOnline: Boolean!
}
type Query {
userStatus: UserStatus!
}
type Subscription {
userStatusUpdated: UserStatus!
}
`;

Create a new PubSub instance for the publish-subscribe mechanism and define resolver functions for the query and subscription defined in the schema above.

const pubsub = new PubSub();
const resolvers = {
Query: {
userStatus() {
return userStatus;
},
},
Subscription: {
userStatusUpdated: {
subscribe: () => pubsub.asyncIterator(['USER_STATUS_UPDATED']),
},
},
};

Create the GraphQL schema from TypeDefs and Resolvers:

const schema = makeExecutableSchema({ typeDefs, resolvers });

Create an express app and an HTTP Server for our HTTP requests:

const app = express();
const httpServer = createServer(app);

Create a Websocket Server and its cleanup to support our Websocket operations:

const wsServer = new WebSocketServer({
server: httpServer,
path: '/',
});
const serverCleanup = useServer({ schema }, wsServer);

Create an ApolloServer instance, and add plugins for the proper shutdown of HTTP and WebSocket instances respectively.

const server = new ApolloServer({
schema,
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
{
async serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose();
},
};
},
},
],
});
await server.start();
app.use('/', cors(), bodyParser.json(), expressMiddleware(server));

Start listening with the help of our HTTP server:

const PORT = 4000;
httpServer.listen(PORT, () => {
console.log(`🚀 GraphQL Server ready at http://localhost:${PORT}/`);
console.log(`🚀 GraphQL WS ready at ws://localhost:${PORT}/`);
});

Since we do not have anything to actually publish a change, we will mimic it with the help of a toggleUserStatus function. This function will toggle the user’s online status every 5 seconds.

let userStatus = {
userId: "ceqak08y3sjkbasdfausjg",
isOnline: true
};
function toggleUserStatus() {
userStatus.isOnline = !userStatus.isOnline;
pubsub.publish('USER_STATUS_UPDATED', { userStatusUpdated: userStatus });
setTimeout(toggleUserStatus, 5000);
}
toggleUserStatus()

That’s it. Here’s the complete file wsIndex.js.

import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import { createServer } from 'http';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
import { PubSub } from 'graphql-subscriptions';
import { gql } from 'graphql-tag';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
async function startServer() {
const typeDefs = gql`
type UserStatus {
userId: String!
isOnline: Boolean!
}
type Query {
userStatus: UserStatus!
}
type Subscription {
userStatusUpdated: UserStatus!
}
`;
const pubsub = new PubSub();
const resolvers = {
Query: {
userStatus() {
return userStatus;
},
},
Subscription: {
userStatusUpdated: {
subscribe: () => pubsub.asyncIterator(['USER_STATUS_UPDATED']),
},
},
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
const app = express();
const httpServer = createServer(app);
const wsServer = new WebSocketServer({
server: httpServer,
path: '/',
});
const serverCleanup = useServer({ schema }, wsServer);
const server = new ApolloServer({
schema,
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
{
async serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose();
},
};
},
},
],
});
await server.start();
app.use('/', cors(), bodyParser.json(), expressMiddleware(server));
const PORT = 4000;
httpServer.listen(PORT, () => {
console.log(`🚀 GraphQL Server ready at http://localhost:${PORT}/`);
console.log(`🚀 GraphQL WS ready at ws://localhost:${PORT}/`);
});
let userStatus = {
userId: "ceqak08y3sjkbasdfausjg",
isOnline: true
};
function toggleUserStatus() {
userStatus.isOnline = !userStatus.isOnline;
pubsub.publish('USER_STATUS_UPDATED', { userStatusUpdated: userStatus });
setTimeout(toggleUserStatus, 5000);
}
toggleUserStatus()
}
startServer()

Start the servers using node wsIndex.js and here we go!

As you can see in this video, the updates automatically get published to the API playground by the GraphQL server. Now using these subscription updates, the client can toggle the online status of the user on the frontend.

Conclusion

In conclusion, subscriptions are the way to support real-time websocket-based use cases in a GraphQL server. They are ideal where bi-directional communication is needed, use cases where latency is important and the payload size is minimal. We learned how to build a basic GraphQL server, write resolver functions to support data fetching for our query and mutations, and we also went through an in-depth advanced example that demonstrates how to set up and use GraphQL subscriptions.