Skip to content

Instantly share code, notes, and snippets.

@gaerfield
Last active August 20, 2020 17:03
Show Gist options
  • Save gaerfield/77b3d801fc225568fea0c22a274fa424 to your computer and use it in GitHub Desktop.
Save gaerfield/77b3d801fc225568fea0c22a274fa424 to your computer and use it in GitHub Desktop.
Graphql-thougts

GraphQL vs. REST vs. RPC

REST is a concept to decouple server and client by providing an API providing access to server-side data as ressources and provide methods to change these ressources.

RPC on the other hand is a binary protocol for invoking Procedure at a remote-Computer. In its simplest form an port is opened processing data in an closed binary protocol. A more standard-approach would be using SOAP+XML.

GraphQL is a Query-Language, specification and set of tools operating on a single http-endpoint. With the query-language the client is allowed to define, which data it wishes to receive and thus possibly reducing the number of requests and the amount of data to be send.

With Spring-Boot and several other frameworks REST-endpoints are very easy to implement and allowing a good access to a domain-model. Some kind of operations don't act on a single ressource. They don't result in creating a new ressource or they maybe changing multiple ressources at once. Such operations are easier to implement as RPC-endpoint. That not neccessarily mean to switch to a different framework. It just means to distinguish between them, for example on URI-Level. With "/document/{id}" it's pretty clear, what ressource is affected. And with "/api/calculateCitationIndex" it's pretty clear, a remote-procedure is triggered (this one explains it well: https://www.smashingmagazine.com/2016/09/understanding-rest-and-rpc-for-http-apis/).

REST has the advantage to be cacheable, while GraphQL works better with evolving APIs and allowing to serve mutliple different clients (https://phil.tech/api/2017/01/24/graphql-vs-rest-overview/) - in fact some of the domain-knowledge is offloaded to the client (they need to know how the domain looks like to build their queries).

All variants can coexist in the same project and it maybe makes sense to utilize them. Within Payfree, the relevant Stores (depending on users coordinates), Configuration and Purchased items change a lot and are maybe better suited for GraphQL than REST.

In my opinion we need to ask:

  • Will the API be public and do we allow to develop third-party-apps using that API (imagine it like twitter)?
    • If yes: we should carefully design the api (considering also support for HATEOAS, Siren, or Hydra - containing more meta/schema-information)
    • If no: REST is easy and fast to implement and we should be fine.

Also theres a flow-chart for easier decision on that topic: https://phil.tech/2018/05/21/picking-an-api-paradigm-implementation/

Graph-QL is Query-Language that allows clients to define exactly, what information it would like to receive. What information could be retrieved is given within a typed schema provided by a Graph-QL-Server. This has advantages on different levels:

  • Because of the typed schema multiple tools where developed (like Altair), that allows code-completions to easily define queries against a Graph-QL-API
  • Beause the client must explicitely define, which properties it would like to receive, over-fetching (receiving to much data) and under-fetching (receiving not enough data) is prevented
  • Because over-fetching is prevented, less data must be send to clients and therefore results in less bandwith-usage / needs
  • Because under-fetching is prevented, the clients can get all information within a single request and must not ask for more data in further requests
  • REST would normally define different endpoints to prevent over-/under-fetching which can result in different APIs (one API for every client), this can be prevented with GRAPH-QL
  • GRAPH-QL recommends not to remove properties/attributes and instead just adding new ones to the schema, so it stays backwards-compatible and would not need version-numbers.
    • REST in comparison says, you should use HATEOAS (or similar schema-definitions) to achieve "version-less" public APIs
    • so REST and GraphQL can both evolve, but GraphQL seems slightly better suited for this Job

The advantages of GRAPH-QL make it especially useful when used within low-latency, low-bandwith environments (like mobile-applications). But the approach introduces new implications to the architecture:

  • the n+1 problem arises, because for a single graphql-query the costs of the query cannot be predicted in advance (i.e. in terms of db-requests). Caching needs to be implemented carefully (https://itnext.io/what-is-the-n-1-problem-in-graphql-dd4921cb3c1a).
  • within the java-world there are only few libraries and nearly no documentation about best-practice-examples
  • graphql-kotlin(https://github.com/ExpediaGroup/graphql-kotlin)
    • integrates with spring
      • built upon graphql-java it needs some not-so-nice language-constructs because it falls back to java
      • needs to define classes which then are mapped to the graphql-model
        • which introduces model-duplication (as it often has tendencies to just duplicate the domain)
        • mixes model and retrieval of model-attributes
        • it feels more like java-implementation, then a kotlin-implementation
  • KGraphQL (https://github.com/aPureBase/KGraphQL)
    • pure kotlin
      • DSL for schema-definition (this seems a bit nicer then the classes-approach)
      • no caching and stuff
      • no Spring-Integration
  • currently no library supports asynchronously streaming data to clients for a query (graphql-kotlin does this for subscriptions, but this has again other problems)

In Summary: while interesting currently I have not found best-practices how a clean architecture with a GraphQL-API could look like. This makes it risky to adopt the approach for long-running projects. Nonetheless a dual-approach could make sense, providing mainly REST-Services and also implementing GraphQL for parts of the system, where it can play out its advantages (this still has costs, because two API are more expensive than a single one).

plus-side:

  • no over-fetching
  • no under-fetching
  • single API for different devices
  • allows slightly better API-evolution compared to REST
  • client must explicitely say, which properties it would like to have
  • allows fetching data within single request

minus-side:

  • n+1 Problem
  • architectural implications
  • (poor library-support)
  • costs of a request cannot be predicted in advance
  • support of reactive model only in parts (subscriptions)
  • single-endpoint no Http/Html-caching can be applied
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment