Getting started with subscriptions

This guide shows how to start using subscription capabilities on a GraphQL server.

If you use Apollo Studio, make sure to select the graphql-ws implementation in the connection settings.

Enable subscription capabilities

Before using subscriptions on a GraphQL server, you must enable them by passing the subscriptions feature to Neo4jGraphQL:

new Neo4jGraphQL({
    typeDefs,
    driver,
    features: {
        subscriptions: true
    },
});

Install dependencies

Then, the next step is to install the following dependencies:

npm i --save ws graphql-ws neo4j-driver @neo4j/graphql express @apollo/server body-parser cors

Set up an @apollo/server server

Add the following code to your index.js file to implement a simple @apollo/server server with subscriptions (for more options, see Apollo’s documentation):

import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import bodyParser from 'body-parser';
import cors from "cors";
import { createServer } from "http";
import neo4j from 'neo4j-driver';
import { Neo4jGraphQL } from '@neo4j/graphql';
import { WebSocketServer } from "ws";
import { useServer } from "graphql-ws/lib/use/ws";
import express from 'express';

const typeDefs = `
    type Movie {
        title: String
    }

    type Actor {
        name: String
    }
`;

const driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("username", "password"));

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    driver,
    features: {
        subscriptions: true
    },
});

async function main() {
    // Apollo server setup with WebSockets
    const app = express();
    const httpServer = createServer(app);
    const wsServer = new WebSocketServer({
        server: httpServer,
        path: "/graphql",
    });

    // Neo4j schema
    const schema = await neoSchema.getSchema();

    const serverCleanup = useServer(
        {
            schema,
            context: (ctx) => {
                return ctx;
            },
        },
        wsServer
    );

    const server = new ApolloServer({
        schema,
        plugins: [
            ApolloServerPluginDrainHttpServer({
                httpServer
            }),
            {
                async serverWillStart() {
                    return Promise.resolve({
                        async drainServer() {
                            await serverCleanup.dispose();
                        },
                    });
                },
            },
        ],
    });
    await server.start();

    app.use(
        "/graphql",
        cors(),
        bodyParser.json(),
        expressMiddleware(server, {
            context: async ({ req }) => ({ req }),
        })
    );

    const PORT = 4000;
    httpServer.listen(PORT, () => {
        console.log(`Server is now running on http://localhost:${PORT}/graphql`);
    });
}

main();

This setup uses the default subscriptions mechanism suitable only for development, testing, and single instance servers. If you need to scale horizontally for a production-ready application, see Horizontal scaling.

GraphQL subscriptions

With the previous server running, the available subscriptions are set for Movie and Actor. You can subscribe to new movies created with the following statement:

graphql
subscription {
    movieCreated(where: { title: "The Matrix" }) {
        createdMovie {
            title
        }
    }
}

With that, any new movie created with the matching title will trigger a subscription. You can try this with the following query:

mutation {
    createMovies(input: [{ title: "The Matrix" }]) {
        movies {
            title
        }
    }
}

Further reading

Keep reading this section on Subscriptions for more information and advanced examples.