Real-World Reasons To Use GraphQL

By Scott Blackburn, Principal Software Development Engineer, Workday

For building data-driven apps, GraphQL changes the game. There are a lot of great blog posts that give an overview of GraphQL, or detail why GraphQL is better than REST, but we’re going to talk about why GraphQL worked well for us building a real-world, production app.

I joined Workday as part of the SkipFlag acquisition. At SkipFlag, we built an AI-powered knowledge base that leverages existing conversations, support tickets, and other communication to understand the people, topics, and facts within a company to autonomously answer questions (and we’re super excited to be bringing that technology to Workday). As one can imagine, building APIs for an application with many rich, interconnected data types is a significant challenge. We started with traditional REST APIs, but eventually tried GraphQL, and never looked back.

Screenshot of SkipFlag — GraphQL makes it much simpler to build modular, data-driven apps like this.

GraphQL at SkipFlag

GraphQL made us more productive and enabled us to adapt and evolve our product more quickly than we thought possible. There were many reasons why we loved GraphQL, but we’ll highlight three of them:

1. Client-driven API

Using REST APIs, client development for complex, multi-platform, data-driven applications like SkipFlag has traditionally required (or at least frequently resulted in) a bunch of custom endpoints. Custom endpoints are difficult to keep consistent, onerous to test, and duplicate code.

With GraphQL, the API specifies all of the data that is available, and each client requests exactly what it needs. This allows client development to move faster and more independently.

Have a mobile view that uses a limited set of fields of a type? GraphQL only retrieves the fields requested. Need to make a batch request for several objects (or several different types)? GraphQL allows the use of aliases instead of having to explicitly create batch APIs:

// Query with aliases
{
note1: note("note1") {
...
}
note2: note("note2") {
...
}
}
// Result
{
"data": {
"note1": {
...
},
"note2": {
...
},
}
}

Giving the client the ability to make arbitrary requests for any available data removes a lot of the pain of API development. As an example, at SkipFlag we completely redesigned the home page of our application several times, but because of GraphQL, the redesigns required almost no changes to the API. Modules were moved, added, removed, or significantly altered, and all that had to be done to get the necessary data was to update the GraphQL query.

2. Relay (and other great client frameworks)

Relay is a JavaScript framework for building React applications powered by GraphQL. Relay allows React components to declare their own data dependencies in GraphQL (usually via “fragment containers”), and Relay (specifically QueryRenderer components) will guarantee the data is fetched before rendering the component. This coupling of GraphQL data dependencies with React components makes composition and reuse of components incredibly simple and powerful.

Let’s take the example of a basic component that can display a User’s name:

class Username extends React.Component {
render() {
return (
<span>{this.props.user.name}</span>
);
}
}
export default createFragmentContainer(
Username,
graphql`
fragment Username_user on User {
name
}
`
);

Now we’ll create a Note component that leverages Username to display the author:

class Note extends React.Component {
render() {
return (
<div>
<p>{this.props.note.contents}</p>
<p>By: <Username user={this.props.note.author}/></p>
</div>
);
}
}
export default createFragmentContainer(
Note,
graphql`
fragment Note_note on Note {
contents
author {
...Username_user
}
}
`
);

Notice that Note doesn’t need to know anything about what data Usernamerequires, other than it must be of type User.

Now if we want to, for example, change Username to also link to a User’s profile, we just update the Username component:

class Username extends React.Component {
render() {
return (
<a href={this.props.user.profileUrl}>
{this.props.user.name}
</a>
);
}
}
export default createFragmentContainer(
Username,
graphql`
fragment Username_user on User {
name
profileUrl // <-- New data dependency
}
`
);

No changes to Note (or any other component that includes Username) are required. This sort of data dependency declaration and fragment composition really shines in apps like SkipFlag where you have common data types used in many different modules. For example, a UserAvatar component can be used for the author of a Note, a participant in a Conversation, and as the organizer of an Event.

(Apollo is another great framework with many similar concepts.)

3. GraphiQL

Another major benefit provided by GraphQL is the ease with which the API can be tested and browsed using GraphiQL. GraphiQL describes itself as a “graphical interactive in-browser GraphQL IDE.” It allows developers to easily write (with autocomplete) and issue any query, view the results, and navigate the schema via automatically generated documentation. Most GraphQL server implementations come with built-in support for GraphiQL, and it’s simple to configure and run for those that do not.

It’s hard to overstate how useful a tool GraphiQL is when developing both the API and the client.

When you have a complex data set with many nested, interconnected types, it’s invaluable to be able to browse the schema and easily exercise the API. Need to debug a query that’s throwing an error? Copy the query over from the client, run it, and modify as necessary. Not sure what the new types added last week actually do? Hop into the schema documentation and browse around. Testing a new type and can’t recall the name of a field when writing the query? Autocomplete to the rescue.

Learn More

GraphQL was an incredible boon to our productivity at SkipFlag. GraphQL has a great ecosystem and a large (and growing) list of major users.

If this post has piqued your interest in GraphQL, head over to https://graphql.org/learn/ to dig deeper and try it out.

Other Links