Subscription Plugins

Subscriptions are only available as a beta; its API may change in the future. It is not recommended to use subscriptions in production environments.

Plugins are used to enable subscriptions in @neo4j/graphql and to allow easy connection to different message brokers. This is required to run a production system with horizontal scaling.

Official plugins

The following plugins are supported officially by @neo4j/graphql:

  • Single Instance - A plugin for use within a single instance of the GraphQL library, exported directly from the library.

  • AMQP - Connect to AMQP brokers such as RabbitMQ.

Create a custom plugin

If none of the existing plugins is valid for your use case, you can create a new plugin to connect to any broker you may need. To do this you need to create a new class defining your plugin. This class needs to contain the following:

  • An EventEmitter property called events that should emit an event everytime the broker sends a message.

  • A publish method that will publish a new event to the broker.

  • Optionally, a init method returning a promise, that will be called on getSchema. This is useful for setting up the connection to a broker.

For instance, if we wanted to subscribe using redis:

// Note: This is an example of a custom plugin and not a production ready redis plugin
class CustomRedisPlugin {
    constructor(redisClient) {
        this.client = redisClient;
        this.events = new EventEmitter();
    }

    // This method connects to Redis and sends messages to the eventEmitter when receiving events.
    async init(){
        await this.client.connect();
        this.subscriber = this.client.duplicate()
        this.publisher = this.client.duplicate();
        await this.subscriber.connect();
        await this.publisher.connect();

        await this.subscriber.subscribe("graphql-subscriptions", (message) => {
          const eventMeta = JSON.parse(message);
          this.events.emit(eventMeta.event, eventMeta); // Emits a new event when receiving a new message from redis
        });
    }

    async publish(eventMeta) {
        await this.publisher.publish("graphql-subscriptions", JSON.stringify(eventMeta)); // Sends a message to redis
    }
}

const client = createClient(); // From https://www.npmjs.com/package/redis
const redisSubscriptions = new CustomRedisPlugin(client)

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    driver,
    plugins: {
        subscriptions: redisSubscriptions,
    },
});

Note that, like in the previous example, extra properties and methods are often needed to handle the connection to the broker. As long as the messages are sent to the broker in the publish method and that these messages are received and then emitted through the events property, the subscriptions will be properly handled.

Using Typescript

If using Typescript, you may import the interface Neo4jGraphQLSubscriptionsPlugin to implement your own plugin:

class CustomRedisPlugin implements Neo4jGraphQLSubscriptionsPlugin {}

Note about event orders

Events are sent to the plugin in order, however, order is not guaranteed once these events have been broadcasted through a broker. For cases when ordering is important, the subscriptions payload contains a field timestamp.