Apollo Graphql and Kotlin: create a back-to-back subscription system

What is Apollo ?

Apollo is a framework that makes it easy to use Graphql. It is available in several languages, and there is a client and server version.

The strength of Apollo Graphql is, above all, the standardization of your API, its self-documentation and its flexibility in the resolution of the answers, especially thanks to the schema system and test tools like playground.

Why back to back?

Most of the Apollo usage examples tell you how to create an Apollo Graphql server in Node.js with a single page js client application.

I recently needed to implement a push server for a Kotlin client using the bot TOCK framework. So my client is a Kotlin server that pushes on Facebook Messenger.

Architecture

Below a representation of the architecture we are going to create :

A WebSocket between servers? This is not the case of conventional use, but it is a way to share the push server with Android or Web clients. It is moreover the only option for a Facebook Messenger client bot, because we have to handle the connection server side.

For more intensive and industrialized use, there is also a Node.js Apollo Redis package to replace the socket between the 2 servers.

Server node

On the server side, I use the apollo-yoga package. It allows a simple and concise configuration of an Apollo server. The use case is very basic, it is simply a CRUD on a message object with a title and content. I will not detail the code contained in the resolvers services, which is only Mongoose code to persist the data in a mongoDb database.

Schéma Graphql

The schema that describes GraphQl objects and methods.

Resolvers

The resolvers correspond to the code that processes the different GraphQl queries. The types are Query (read), Mutation (write), Subscription.

Index Schema

Construction of our schema vs the resolvers. This code will crash at runtime if the resolvers do not exist or if the schema is bad.

Index serveur Node.js

Client Kotlin Server

For the client code I chose to use Apollo Android. This project is the most successful I found of the ecosystem to generate client Java code.

Project Android

Vous pouvez créer ou utiliser une configuration gradle dans votre projet. Pour ma part j’ai opté pour la solution de facilité, à savoir suivre la doc de Apollo Android avec un projet Android vide et Android Studio.

You can create or use a Gradle configuration in your project. I opted for the easy way, which is basically following the doc of Apollo Android with an empty Android project and Android Studio.

Schema.json is the result of an introspection query with apollo-codegen :

Other files must contain your query / mutation / subscriptions in the query client format :

You need to modify your Gradle files to import Apollo dependencies.

In the global Gradle file :

In the app’s Gradle file :

The code is generated after a Gradle build in app/build/generated/source/apollo

Generated code

Simply copy the code into your Kotlin project. You can also create a dependency on your internal Nexus for example.

Apollo Instance and WebSocket

The WebSocket opened by Apollo is based on the library ok http 3, so it is standard in the Kotlin ecosystem.

Apollo client code :

This code is necessary to create instances of the different generated services (Client Http, WebSocket). We can see the url of our Node.js server :

Class WebSocket :

This is where the pushes in the socket are retrieved :

Example of a socket update with a push to Facebook Messenger and bot TOCK framework code :

Manual tests with playground

Playground also helps you manually test and document your GraphQl server with a clear and convenient interface :

There is also a mock mode for GraphQl that can be used for your unit tests with for example Mocha and Chai.

Deployment

Deploying the server itself is not complex, it’s easy to deploy a Node.js application on AWS or GCP. The tricky point is the management of the WebSocket. For example, in an ElastikBeanstalk Aws instance, you will need to change the basic Nginx configuration for the HTTP upgrade request to be handled (switch to the WebSocket protocol).

That’s why I deployed my app on Heroku. WebSockets are managed there. Just think of pinging the socket regularly, which turns off every 55s by default :

Theoretical limits

It is difficult to calculate the theoretical limit of connections on a WebSocket. Indeed it depends on the power of the machine, bandwidth, Node.js parameters, File descriptors, … However we can for example make 600k connections on an Amazon M3.xlarge machine.

To overcome this type of limit as indicated above, the best is to change architecture on a back-to-back case to a queuing type redis solution: Apollo Redis

Amazon implementation

There is a similar and higher level Apollo implementation at Amazon: AppSync. This service will allow you to create a GraphQl server quickly. But beware, you will be much less free on the resolvers code, which is very resolution-oriented in the Amazon type DynamoDb ecosystem, based on code templates.

Conclusion

GraphQl brings a very standardized and framed architecture, while allowing a great flexibility in the resolvers. This tool is gaining more and more space against our classic REST APIs. Be careful though, this makes the api exposed much simpler to explore, and potentially hackable. Do not forget to protect your server from malicious queries in your resolvers, to use authentication tools like express-jwt or express-ipfilter to filter access to your playground and schema by login or IP.

Fullstack software engineer @Oui.sncf. I love discovering new technologies. Tech is as important as his usage.