From REST to GraphQL: Improving the Resilience of Client Applications

Jude Séïde
SSENSE-TECH
Published in
5 min readDec 2, 2022

Since its introduction in 2000, RESTful architecture has become the industry standard for designing web APIs. REST uses the standard CRUD HTTP Verbs, leverages HTTP conventions, and is centered around data resources.

Introduced by Meta as a specification, GraphQL proposes a new standard aiming to solve the shortcomings of REST APIs. In particular, the need for APIs to be able to adapt to the rapid changes required by client applications.

At SSENSE, our Federated GraphQL journey started with the desire to reimagine the front-end API, and we set out to solve problems around ownership and velocity, rather than complexity.

In our last article, we talked about the hidden costs of non-nullable fields. Here we will discuss how to leverage the nullability and the flexibility of GraphQL to improve the resilience of client applications.

Is GraphQL the Better REST?

The two approaches have a lot in common, such as stateless services and structured access to resources. For both, we need to write efficient code for performance and data availability.

In both approaches, we send requests and expect responses over HTTP, make “endpoints” available, and need to be proactive when it comes to security.

However, REST APIs have shown to be too inflexible to keep up with the rapidly changing requirements of the clients that access them.

Developers using REST APIs often have to make multiple requests and deal with unwanted data in order to find relevant information. Custom and non-restful endpoints are often requested as a solution.

This creates friction between the API maintainers and consumers, respectively wishing to keep their restfulness as opposed to satisfying use cases without unnecessarily laborious data parsing and back-and-forth requests.

GraphQL was developed to cope with the need for more flexibility and efficiency. It solves many of the shortcomings and inefficiencies that developers experience when interacting with REST APIs.

GraphQL provides a query language and a robust type system that empowers developers, giving them autonomy over querying APIs and thereby increasing the velocity of front-end teams.

Client applications retrieve only the data needed, avoiding manual code parsing and data filtering that takes up precious processing cycles when rendering the UI to users.

Resiliency Patterns

Anticipating failure is crucial, especially at a company with the technical complexity and high volume of traffic that SSENSE sustains. This means building resilient applications must account for the crash of services as well as detect slow and poor performance.

At SSENSE we use redundancy techniques such as running multiple instances of a service, simple timeouts to fail fast and kill a request, as well as more advanced retry mechanisms and circuit breakers.

GraphQL Trump Card

These resiliency patterns are technology agnostic and can be used with REST and GraphQL, the latter having an advantage with its built-in graceful degradation mode.

In fact, a GraphQL operation might return partial data even if some resolvers produced errors. This means that some of the requested data will be included in the API’s response, a contrast with REST where only an http status code and some error message will be provided.

Combined with intentional nullability and code generation, this is a powerful tool to build more resilient applications. Front-end developers and UI/UX designers can now predict which data might not be available and proactively decide the behavior of an application based on data availability.

Strategies for Improvements

Using Fragments to Describe Data Needs

A GraphQL fragment is a reusable section of a query or mutation, used to represent some logic. Data dependencies can be colocated with their components, instead of writing a large GraphQL operation.

Using fragments is particularly useful in the context of a federated GraphQL architecture. Let’s consider the schema below and a scenario where different subgraphs enrich the product entity to add data such as price, and availability, or more static data such as brands.

We can represent the product tile of a listing page with a fragment and colocate it with a UI component.

Now, what happens if the pricing service is unavailable but we are able to resolve all the other fields? Do we display a blank page with no products or do we let the customer browse with a save for later button as a fallback?

The hero here is the schema. Thanks to it, we know some fields could be null; it’s up to us to decide how to prepare for that eventuality.

Using @defer and @stream Directives to Improve Latency

The @defer and @stream directives are mechanisms that allow GraphQL servers to return multiple payloads from a single GraphQL response, thus speeding up the time-to-interaction of front-end applications.

Let’s say that we want to display some personalized recommendations for a user on a product detail page. And let’s suppose fetching this data is generally slower.

The @defer directive allows marking specific fields as non-essential for immediate returns. We can accomplish our objective without impacting performance or user experience by receiving deferred data asynchronously.

Like @defer, the @stream directive is a way to request data as soon as it’s available from the GraphQL server. We can, for instance, stream large amounts of data, lists, etc.

A caveat is that support for these directives depends on the GraphQL server library used, so your mileage may vary.

Using @include and @skip Directives to Control Optional Fields

The @include and @skip directives are operation-exclusive, meaning they are flags telling the GraphQL server to resolve or not the decorated field or fragment.

Therefore, we can leverage this ability to conditionally fetch more or fewer data to build reusable components or feature flag sections in our queries.

Let’s revisit the product recommendation scenario above and imagine we’re expecting an influx of requests due to new releases from a popular brand. We may decide then to ease the load by temporarily disabling the expensive personalized recommendations.

Conclusion

Is GraphQL the better REST? Like most things in tech, the answer is likely “it depends” on your context. The former offers a number of advantages including a schema acting as both a contract and API documentation.

For front-end teams, in particular, the ability to predict data availability and leverage that to design an application can tremendously impact the user experience and improve the resilience of client applications.

Furthermore, the ability to prioritize important data and positively impact latency as a consumer of an API solidifies how much GraphQL is empowering developers.

Editorial reviews by Catherine Heim, Mario Bittencourt & Nicole Tempas.

Want to work with us? Click here to see all open positions at SSENSE!

--

--