Horizontal scaling

Horizontally scaling any real time system can be complex, especially when dealing with long lived connections such as WebSockets. Consider the following example, in which Client A is subscribed to a certain event that is triggered by Client B:

diagram1
Figure 1. Basic subscriptions setup example

The server running the GraphQL service does the following:

  1. Receives the mutation by Client B.

  2. Runs the Cypher query on Neo4j.

  3. Triggers the subscription event to Client A.

This setup works for a single instance of a @neo4j/graphql server. However, when trying to scale horizontally by adding more GraphQL servers, you may encounter the following situation:

diagram2
Figure 2. Subscriptions with 2 servers

In this case, Client B is subscribed to one server. However, when Client A triggers the mutation, it may query a different server.

The change happens successfully in the database, and any client connected to the same server receives the subscription event. However, Client A does not receive any update, as the server it’s connected to does not get notified of any mutation.

This is the default behavior of the subscription engine provided by the library, making it unsuitable for use in a horizontally scaled environment.

Using PubSub

One solution to this problem (as well as how @neo4j/graphql is intended to work) is to use a PubSub pattern with an external broker to broadcast events through multiple instances. This can be achieved through different Subscription engines.

Following the previous example, using an intermediate broker to broadcast the events across all instances, the infrastructure would look like this:

diagram3
Figure 3. Subscriptions with 2 servers and a message broker

The events are as follow:

  1. Client B queries the first server.

  2. The server performs the mutation in the database.

  3. The same server sends an event to the broker.

  4. The broker then notifies every server (broadcast), including the server that originally triggered the event.

  5. Both servers receive the notification and trigger any event to their subscribed clients.

Further reading

You can find more examples of this type of pattern with @neo4j/graphql on Subscription engines.