How and Why We Adopted GraphQL

Hootsuite Engineering
Hootsuite Engineering
5 min readDec 21, 2017

Introduction

Are you tired of having to make mobile specific APIs? Isn’t it just the most thrilling experience to have to parse through an extra long return payload just for one tiny piece of information? What if we could ask for specific parameters? Developers at Hootsuite have an answer to this question (or rather, developers at Facebook created the solution to this problem, and developers at Hootsuite adopted this solution!); introducing GraphQL — a query language for your APIs where you can define your own type system and routes.

About GraphQL

GraphQL Users can specify exactly what they want from the server -

{
Human (id: "1000") {
name
height
}
}

Above example is straight from GraphQL documentation and demonstrates just how selective you can make your queries. You’d be asking for the Human object with the id “1000” and only the name and height parameter of that object. So now you don’t need to dig through Human’s 40 different parameters!
That’s pretty convenient, but GraphQL gets even better — what if you had to fetch that Human’s user Id, make another call to the service for its posts, and another call for the posts’ comments, and another call for those comments’ authors? This would be a whole number of calls and things would get messy really quickly — in GraphQL, this could be just one call that looks something like this.

{
Human (id: "1000") {
posts {
comments {
author {
name
}
}
}
}
}

REST vs GraphQL

So why veer from well established practises like REST and enter unknown battleground like GraphQL? First thing you should understand is that GraphQL doesn’t mean we completely abandon REST. Your GraphQL service is going to need to communicate with your external database and your other services somehow, whether that’s websocket, or http — which would essentially mean you still use REST protocols.

Why and How Hootsuite uses GraphQL

At Hootsuite, we leverage GraphQL as the middle abstraction layer; the front end clients only see GraphQL and the backend microservices only see GraphQL. Beauty of this is we can add as many backend microservices as we want, and the frontend only ever has to call our GraphQL service.

One of the biggest reason Engage team at Hootsuite decided to use GraphQL was mobile enablement — we wanted to use same Rest API for the mobile and web team, and to overcome certain inherent differences between web and mobile (ie. mobile’s sensitivity to payload size, battery consumption on polling, etc); we wanted the client to have control over what they get from the server rather than the server having that control. Also, it was a new technology that opened us up to new possibilities — I think it’s bigger company’s role to experiment with bleeding edge technology so that smaller companies can learn from the bigger company’s mistakes and be able to adopt new technology quickly and safely. I was hyped to find out that Hootsuite is using bleeding edge technologies such as GraphQL, Kubernetes, etc.

Difficulties in cross-platform development

GraphQL is great for enabling mobile to use the same API as web and other clients — however, there are a TON of difficulties with this. A big limitation is that mobile is so intrinsically different from web; mobile is more conscious about the payload sizes of its requests, has battery limitations and is harder to continuously develop and deploy. We had to be EXTREMELY conscious about the way we changed the API contract between our GraphQL server and the front-end devices. If we were to change the field ‘words’ to ‘message,’ we would have to change the front-ends to request for ‘message’ instead of ‘words’ otherwise it would break.

type Words {
text: String
linkSpecs: [LinkSpecs!]!
media: [Media!]!
description: String
}

Let’s say the schema looked like this at one point. And then one bright engineer says “hey, that name is pretty unintuitive.” Now we have to fix it. Let’s say we changed the name ‘Words’ to “Message.” So this call that Android was making,

{
Words {
text
description
linkSpecs
}
}

will now return an error, which may cause a crash, which would definitely cause the user to have a bad experience.

But sure, we can just fix the front end to just call for “Messages” instead. This is easy on web — however, that would have to go through a whole process of submitting to Apple or Google for review and wait for it to be deployed through the respective app stores.

Bottom line was — we had to be extremely conscious about decisions we made. Being extremely conscious meant that everyone had to agree on schema changes, which lead to unending discussions.

My team’s process of being on the same page about schema change was through a schema doc. However, every time that schema had to be changed, you still had to consider backwards compatibility, modify the schema, re-generate the schema file based of code changes. The process was not the revolution we hoped GraphQL would bring.

At the end of the day, being really clear on changes being made was good; everyone understood the changes and contributed to the discussions. However, the ability to make changes and experiment with different ways to solve a problem was taken.

Letting the clients choose what they want instead of the server seems so logical, but there are some big blockers in GraphQL-oriented backend design as I’ve demonstrated. I personally think it really drives teams to be more full stack — designing the GraphQL server is difficult without really knowing what each field is meant to do. If I were to be a backend-only developer trying to implement this GraphQL server, creating a clean, efficient service would be extremely difficult.

Final thoughts?

GraphQL is a great way to build your next backend server — as steep as the learning curve may be, it’s at least worth trying out.

About the Author

Ike is a Software Developer Co-op on the Engage team at Hootsuite. He attends University of Waterloo for Computer Engineering, you can connect with him on linkedIn or @ikeleee.

--

--