Using Absinthe and Phoenix Channels side-by-side

Having a hard time conceptualizing how to properly marry Phoenix Channel and GraphQL paradigms.

Say your client server operations are synchronous and you choose GraphQL

Down the line you have to implement realtime operations between users. You could:

  • still use GraphQL: use subscriptions to subscribe to a topic to receive, and use the same mutation pattern you were before, to send. Most likely you will be using Channels to implement Subscriptions

  • just drop into Channels directly, in parallel

Clearly there is overhead in maintaining request handling for both GraphQL and Channels, but something tells me using GraphQL for realtime use cases beyond Subscriptions (as in SSE’s) is smelly. At the same time, it makes sense to route everything thru a single endpoint.

Thoughts ?

1 Like

To narrow down the question:

Does anybody here use Absinthe and Channels in parallel?

I don’t see any reason why it should not work.

But the usage is not the same… GraphQL is optimized for FB usage, it would not fit a realtime game for example. It’s done for text and images.

You did not mention the frontend. GraphQL main target is React, with Relay client, but You can use it with anything using Apollo client.

Can You use Relay client (or Apollo) and channels? Yes of course…
Is it the same usage? No.

1 Like

I know it can work, my question is more along the lines of best practices wrt either having both GraphQL and Channels coexist or consolidating them into GraphQL (or vice versa).

The frontend framework could be anything, but raises the same questions, whether it makes more sense having a GraphQL client and phoenix.js coexist or having all client/server interaction consolidated.

Arguably, GraphQL is a great fit for channels. The problem presented by channels is that by eschewing the traditional HTTP verbs, all of the standard patterns like REST don’t really apply.

GraphQL however is transport agnostic, so making queries via websocket works just fine, and subscriptions make it easy to stay up to date as information in the system changes. We’ve used GraphQL both with React / Apollo via websockets, as well as with separate live view services to great effect.

There is a small amount of boilerplate you need for supporting GraphQL over HTTP as well as channels, but it’s really small. More importantly, it’s a one time up front cost. As you grow your GraphQL schema, you don’t need to change anything.

3 Likes

Awesome, so basically layering GraphQL atop channels rather than having them coexist side-by-side.

This is very interesting and addresses one of my earlier questions: Replacing HTTP with Websockets (or other persistent transport). Why did you choose to transport queries via websockets rather than http? Are there any docs/articles written on this, specifically on the Absinthe side?

What I meant by “maintaining both” was having a scope for GraphQL and another for channels. I.e. you have, say, an Airbnb app whose browse/booking logic is routed to contexts by GraphQL resolvers but whose chat (or realtime bidding or wtv) is routed by channels. Is this an antipattern?

From a basic code perspective, Absinthe only uses a single channel __absinthe__:control and it’s a one liner to add it to your socket. Other than that it stays out of your way. However from a design perspective I agree that it introduces a question about whether to managing the chat via GraphQL or via traditional channels.

We started with HTTP, but once we setup the socket for subscriptions reusing that saves overhead. It isn’t a ton of overhead but hey each bit helps. It doesn’t super duper matter from Absinthe’s perspective so you can do whatever makes the most sense from an end client perspective.

1 Like