Leverage Your REST Ecosystem With GraphQL
The REST API model has been around for a while, ~20 years, in fact! As you can see from the graph (no pun intended) below, GraphQL adoption has grown rapidly since its introduction to the public in 2015.
A REST API producer (provider) has myriad unavoidable concerns like how to present data and what options to provide consumers, as well as what type of access control to use, how to manage error handling, and how to ensure top performance.
On the flip side, an API consumer (typically the app developer) has concerns as well. When dealing with REST APIs, developers ask for data and often must write extensive logic to orchestrate the data they get back. The API consumer has no control over endpoint results or the format of these results.
GraphQL is an API architecture but also a query language that puts control in the hands of the app developer — allowing them to query for precisely the data they need, and in the shape they need it for frontend experiences. It offers developers the simplicity of REST responses (i.e. easy to consume JSON data) with the type of specificity of getting only the data you want. Furthermore, it doesn't matter when the data is coming from multiple backend systems or the responses are formatted in different ways - all this can be abstracted in GraphQL.
In this post, we'll focus on REST backends and assemble a GraphQL layer in front of several different REST API backends. We recently explored this topic in a webinar: Leverage 20 Years of REST Investment with GraphQL.
A Data Consumption Layer Bridges the Gap Between API Consumers and Producers
Given the decades of investment in REST APIs and a migration towards GraphQL by API consumers, it is important to find the right balance that leverages the best of these two models. StepZen's approach to doing this is with a data consumption layer that speaks GraphQL on one side and the language of REST APIs or other backends on the other.
StepZen takes a declarative approach to building the GraphQL API. The advantages of the declarative approach over a programmatic one are:
- It gives the developer a low-code approach to building the API. This avoids the need to write thousands of lines of code and complex logic to create the GraphQL API.
- It allows the system (StepZen) to handle complex capabilities like normalization, stitching, access control, and others needed to run a performant and secure system.
In StepZen, the declarative assembly happens in one of two ways. You can either take a consumer "outside-in" view or a producer "data constructs" view.
In a consumer-centric view, the frontend needs to be hydrated from the backend data sources, but without extraneous information like database names, column names, etc. that are only relevant to the backend. In other words, the developer wants to see the data in constructs that make sense to the application view of the data - constructs like a
order, or the
delivery status make sense here.
The producer-centric view exposes the data objects as they have been designed by the backend teams. That can be as JSON from REST or GraphQL, tabular results from SQL databases, or XML from the older generation of backends. The next question is, how to hand it off to the frontend? The data layer enables abstraction of backend complexity and adds consistency because the system can normalize different backend data and protocols by stitching data from different backends together.
Leverage: GraphQL-enable and Mix & Match REST APIs
Let's see it working! We'll see how a GraphQL layer can consolidate the data available via numerous REST APIs, making it easy for the app developer to consume it.
We'll begin by taking a look at the completed GraphQL endpoint that consolidates different REST backends. This example shows how StepZen ties backends together - we'll go into a deep dive in the next post to show some of the code behind the magic.
Consolidation: One GraphQL Endpoint
We've got five REST APIs deployed to our endpoint:
GraphQL has a robust environment of query tools. At StepZen, we use the GraphiQL Query Editor, with some StepZen twists. We make it available on your
localhost:5001 by running
stepzen start with the
--dashboard=local flag. Here's what it looks like for this example project.
The default way to test your GraphQL endpoint is from the StepZen dashboard explorer. You can get a local GraphiQL IDE by running
stepzen startwith the
Zooming in, you can see all the query options for the five APIs in the Explorer window on the left. Note that there are quite a lot of DEV.to options! We were able to generate this rich schema by introspecting the DEV API Open API Spec. Note that we used curl examples to GraphQL-ize Airtable, Google Directions, and Google Places. (More on this in a subsequent blog post.)
Now, let's dive in to see some examples of what's possible with this query editor when we have these five APIs integrated in a single GraphQL endpoint.
Let's see how queries of Airtable, DEV, Google Places and OpenWeatherMap work.
Let's make our first query to Airtable.
As you can see, the query has two parameters,
filterByFormula, which allows the consumer to add a filter, as well as
tableName, which allows the user to point the query at whatever Airtable table they want.
Next, up, one of DEV's queries:
We've found one of StepZen's blog posts by its DEV id!
If you're looking for burritos in the Phoenix area, the Google Places API can help:
Lastly, let's look at an OWM query:
There, we've found the temperature by city - looks like it's a nice cool day...for Miami 😉
You might have noticed that our Airtable request returned a customer, along with their location and address. What if we wanted to know what the weather was like for the location, to make sure that a package of candles we send does not melt en route?
You might already be thinking of boilerplate resolvers to connect these two queries, but there's an easier and quicker way with one of StepZen's custom directives. We'll take a look at that in our next post, which will illustrate the beneficial aspects of this integrated solution for both API provider and consumer.