graphql-over-http icon indicating copy to clipboard operation
graphql-over-http copied to clipboard

Consider adding SSE for Subscription operations to the specification

Open n1ru4l opened this issue 2 years ago • 11 comments

Server-Sent Events (SSE) is a server push technology enabling a client to receive automatic updates from a server via an HTTP connection, that does not require any complex protocol compared to WebSocket, thus making it a perfect fit for having a recommended and standardized way of doing GraphQL Subscriptions in the GraphQL over HTTP specification.


  • https://github.com/enisdenjo/graphql-sse
  • https://www.graphql-yoga.com/docs/features/subscriptions

n1ru4l avatar Jul 07 '22 19:07 n1ru4l

We definitely intend to do this (I've been speaking with @enisdenjo about it) but it is out of scope for the 1.0 release which we basically need to feature freeze right now in order to try and get it cut along with the GraphQL spec in October.

benjie avatar Jul 08 '22 07:07 benjie

Currently a GraphQL over SSE Protocol RFC.

Even though SSE is indeed quite simple, there are some "complexities" added to the Protocol which aim to overcome common problems, just to name a few:

  • The "single connection mode" aiming to help with HTTP/1 servers and subscription heavy apps
  • The requirement of reporting GraphQL operation errors through the established SSE connection instead of the HTTP response because of the ultra vague EventSource.onerror
  • The presence of a complete message to distinguish when a connection gets closed because of a network loss vs. when the subscription is actually completed

enisdenjo avatar Jul 08 '22 09:07 enisdenjo

The "single connection mode" aiming to help with HTTP/1 servers and subscription heavy apps

In my opinion, this added complexity can be optional as servers that support HTTP/2 don't need to do this. HTTP/2 support for browsers seems quite high (97%). From quick research, overall the current adoption for web servers is around 44%

n1ru4l avatar Jul 08 '22 09:07 n1ru4l

In my opinion, this added complexity can be optional as servers that support HTTP/2 don't need to do this.

Completely agree! But that is not the only reason, when using HTTP/2 the max number of simultaneous HTTP streams default to 100. Even though this is quite high, I feel like subscription heavy apps might be reaching this limit. One example I could think of is file upload with server processing progress tracking, uploading 100+ files in one swab, and subscribing to every each one of them, might issue problems. However, I agree that this might be a long shot, but I think it's still worth considering.

enisdenjo avatar Jul 08 '22 09:07 enisdenjo

Subscriptions are typically best when really granular (quite the opposite of queries where you want to get everything at once). This means you can unsubscribe from old items in a list and subscribe to new ones as the user scrolls (without affecting the subscriptions to those in the middle). As such, the number of active subscriptions on any one page on a large screen could easily be 30-50, and when you multiply that by all tabs in a browser that's quickly going to break the 100 limit.

benjie avatar Jul 08 '22 09:07 benjie

I totally agree! Applications could easily have more than 100 active subscriptions. Take something like a chat app with channels where the client subscribes to each channel and each member for updates/state changes. Or something twitter-like where you subscribe to each tweet and the authors of these. And with each reply you receive (via the subscription on a tweet), you subscribe to the reply and the author of the reply as well.

Erik1000 avatar Jul 08 '22 09:07 Erik1000

Subscriptions are typically best when really granular (quite the opposite of queries where you want to get everything at once).

That is an interesting take, it would be nice to get feedback from people who build Twitter-like applications. In the past, I moved the subscriptions up in order to reduce the concurrent amount of subscriptions.

For applying live updates to a paginated list I used the following Subscription model before, of course, this differs from the use-case where you only want to update certain properties within a single item. For stuff where you don't care about the exact event though I used to find live queries to be a bit more convenient, those have other issues with paginated data, and I don't wanna pull live queries into this discussion.

type Query {
  notes(first: Int, after: String): NoteConnection!
}

type NoteConnection {
  edges: [NoteEdge!]!
  pageInfo: PageInfo!
}

type NoteEdge {
  cursor: String!
  node: Note!
}

type Note implements Node {
  id: ID!
  documentId: ID!
  title: String!
  content: String!
  contentPreview: String!
  createdAt: Int!
  viewerCanEdit: Boolean!
  viewerCanShare: Boolean!
  access: String!
  isEntryPoint: Boolean!
  updatedAt: Int!
}

type NotesUpdates {
  """
  A node that was added to the connection.
  """
  addedNode: NotesConnectionEdgeInsertionUpdate
  """
  A note that was updated.
  """
  updatedNote: Note
  """
  A note that was removed.
  """
  removedNoteId: ID
}

type NotesConnectionEdgeInsertionUpdate {
  """
  The cursor of the item before which the node should be inserted.
  """
  previousCursor: String
  """
  The edge that should be inserted.
  """
  edge: NoteEdge
}

type Subscription {
  notesUpdates(endCursor: String!, hasNextPage: Boolean!): NotesUpdates!
}

n1ru4l avatar Jul 08 '22 10:07 n1ru4l

I agree that the spec should at least mention Subscriptions, regardless of if if describes some implementation over HTTP or not. Something like "Subscriptions are out of scope of this spec because ....". Just to clear user's possible confusion - where are subscriptions? Currently spec has 0 occurrences of "subscription"

rivantsov avatar Jul 13 '22 05:07 rivantsov

@rivantsov It was mentioned before https://github.com/graphql/graphql-over-http/pull/166

n1ru4l avatar Jul 13 '22 05:07 n1ru4l

well, yes, but mentioned in particular context - POST op, as far as I understood. As a result of discussion Subscriptions were removed from there, resulting in current situation when subs are not mentioned at all. I think we need to fix it. Queries and mutations are mentioned, but subs are not, at all. Should be.

rivantsov avatar Jul 13 '22 15:07 rivantsov

https://github.com/graphql/graphql-over-http/pull/202

benjie avatar Jul 14 '22 13:07 benjie