5.9 Weaknesses of GraphQL

GraphQL has been optimized for modern systems, companies that are embracing future-facing architectures. The world is moving towards microservices, which means that they are breaking their large applications into independent components that communicate with one another via APIs [38]. As we have discussed, REST struggles to scale, a deal-breaker when it comes to microservices. By the nature of this decoupled architecture, there exist significantly more API calls being made, and a lot more updates being made to data schemas in the back-end, which are actions that REST struggles with significantly.

As such, it is important to understand where GraphQL faces issues when serving a microservice architecture, as for more trivial use-cases it may be over-engineered:

  • Schema Design:

    • In a microservice architecture, like all multi-service architectures, each service exposes a certain amount of information about the back-end system, and there are multiple services working in tandem to run your application. To embrace the powers of GraphQL, back-end developers need to stitch all of these services together under a unified schema, which can cause issues around duplication of resources, and conflicting fields between resources.

    • One solution here is Prefixing, where the back-end developer adds a prefix to each of the broadcasted microservices, such the microservices are all logically separated. This adds a layer of abstraction that actually detracts from the centralized promise of GraphQL, as each service is treated as an island, meaning it becomes impossible to concatenate resource relationships across services. The benefits are that this is very easy to implement.

  • Another solution, which is the official recommendation of GraphQL, takes the form of Bonding, where the back-end developer glues the different GraphQL Schemas from each microservice into a uniform interface. In the past, this required developers to manually stitch schemas together, which adds a serious amount of complexity, but the recent launch of Apollo Federation is a significant step in reducing the complexity of this approach [39]. As such, the community is moving towards solutions that are able to get information from multiple services whilst staying true to the GraphQL methodology.

  • Certification and Authorization:

    • GraphQL renders a multi-tiered service as we’ve seen above. On the top level exists the GraphQL server itself, which takes the request from the client and handles the response. Beneath the top level exists the middle tier, which handles communication from the GraphQL server to the various microservices, and the data tier from which the microservices get data to push back up to the GraphQL server.

    • As such, for authorization developers can choose to decide whether a user has permission to operate on a certain resource at the GraphQL server level, or the microservice level, and the answer to this problem culminates as a trade-off between a centralized and distributed architecture. This is actually a trickier problem than developers might anticipate. Let’s assume that all the authorization is done at the GraphQL server level; this would mean that the services fully trust the call of other services, which can lead to vulnerabilities. On the other hand, if authorization is left as a service level decision, then each service needs its own logic and will need to provide different interfaces to different GraphQL requests, which adds complexity. In principle, companies need to define a hybrid approach in which secondary checks are made at the micro-service level for certain requests, but, as exhibited, this is not a simple thing to think through and set up.

  • Routing Design:

    • When a request comes in, the GraphQL server is responsible for routing that request to the correct services from which it can get the information. If the server possesses a single backend service this is very easy, as it will have access to all the information, but if that’s not the case (as is typical of large microservice deployments), then routing the requests efficiently becomes a problem.

    • GraphQL schema stitching is actually a solution here, as it will implicitly route request fragments to the appropriate microservices through the various resolvers that were updated in order to stitch the service schemas together. In this case, no manual intervention is required, unless there exists a conflict in the schema type (i.e an update has been made to the data model in the relevant microservice). There exist some nice properties of GraphQL that can help here, like the fact that developers can define the expected time it will take for a request to execute, so the server has an idea of how to prioritize effectively, but solving this problem requires significant manual effort. Handling the routing of requests is a fundamental problem that needs to be addressed in every GraphQL system, and it is far from simple to handle a large amount of concurrent requests to various services in a reliable and efficient way.

  • Error Handling:

    • With a typical REST query, the response given will typically describe the outcome of the request. For example, if the request succeeds, the client will receive a code 200; if the resource couldn’t be found, the client will receive a code 404. In GraphQL, this isn’t the case; clients will always receive a code 200 meaning the query returned successfully, and any information about errors will be wrapped in the return object. This means client-side developers must write custom logic for error handling that can be tedious and add complexity to the overall system.

Thus, despite the benefits of GraphQL, there exist significant issues that developers face when implementing it in production. However, we believe this friction is true of any new technology seeking to fully disrupt a market, and no aspect of GraphQL’s design seems to be a fundamental limiter of its potential success. It is able to deal with a more complex set of use-cases because it is more complex, and, as with Kubernetes, it may take additional time before a user-friendly version of GraphQL is available to use broadly against a microservice architecture, but, once it does, it will dominate the market. It is our belief that GraphQL is perfectly positioned to capitalize on the architecture of the future, and that as the world moves to cloud and microservice architectures, GraphQL rise to dominate the API ecosystem. However, REST is still the leading solution and so must be accounted for as such.

Last updated