5 Tips for successful GraphQL adoption

Observations and tales from the battlefield

Introduction

I’ve been working with GraphQL in production for almost 2 years now. As of January 2020, the technology is quite mature, there are more users than ever and GraphQL is rapidly becoming a new internet standard. It’s a great time for your company or organization to adopt GraphQL.

The GraphQL ecosystem has grown tremendously, today, there are more options to choose from, powerful frameworks, developer tools, and utilities, as such, it can be overwhelming, and difficult to know where to start.

In this article I will tell some stories about my experience bringing GraphQL to production, I will remark on my observations and talk about different frameworks. I will point out some idiosyncrasies that you may not be aware of. I will also advise new users, describing things simply with a low level of jargon, I will also make some key recommendations and discuss some “gotchas” / things that may be counter-intuitive and/or unreasonable.

1. Demystify misconceptions about GraphQL

It has been said that if you ask 10 people what GraphQL is, you will get 10 different answers. The term can indeed be quite ambiguous, I’ve seen presentations where it’s been described as a ‘client’ technology, I’ve heard it compared loosely to SQL, and I’ve read numerous vague descriptions.

The GraphQL Foundation has a decent outline:

GraphQL is a query language for APIs and a run-time for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

The problem probably stems from trying to find a catch-all statement that resonates with most people. I like to say:

“GraphQL is a language that describes what you have, what you want and provides an algorithm to resolve those requests”,

I’ve found it helpful to give different explanations depending on the context and the audience. If I’m speaking to developers or product managers I will put a different spin on it, maybe highlighting advantages to documentation and domain modeling.

… another popular question is what GraphQL replaces, people will ask whether it replaces REST, they’ll also ask client related things like whether it replaces Redux. It’s important to clear up what GraphQL is and what it isn’t… I’ve found that describing it as a replacement can be too simplistic and sometimes frightens people.

If you intend to pitch GraphQL to your company, try to demystify wherever possible and reduce confusion. Remember many software veterans are quick to dismiss any technology that is considered “en vogue”.

2. Take a principled approach

It may sound weird to say but there was a time many web developers didn’t use best practices- when the web was new, best practices had yet to be developed.

Nowadays best practices are all the rage, developers seek out the “correct” way to do things… I’ve seen veteran engineers, as well as beginners make the same mistake of approaching problems with first principles.

… what do I mean by first principles?, this is a good article on the subject. Effectively, it’s a process of reverse engineering a problem, often deploying Socratic questioning to re-think, re-consider, or second guess something. It happens with juniors because they don’t realize the work has already been done, and it happens with older veterans because that approach was far more prevalent in the past.

It’s not a bad practice per se, and actually, it’s a great way to be creative, but there is a time and a place…it’s become less appropriate in web development, especially in the enterprise space… it’s important to recognize that software is in a different place now, big projects are developed by many smart people collaborating all over the world.

In many ways, the open nature of REST was its downfall, the lack of a standard contract meant there would be no standard contract. GraphQL is backed by large companies and a lot of thought and engineering has gone into defining the “correct” way to use it.

Amazingly I have met engineers who thought “GraphQL is just blah blah blah so… I’ll write my own stack”, I won’t tell you whether they were the junior or the veteran ;)

It’s a mistake to approach GraphQL with first principles, you should follow best practices wherever possible and actively seek out opinions and opinionated software. Jump on an existing open-source implementation if you need to extend it.

Principled GraphQL, written by Geoff Schmidt and Matt DeBergalis of the Apollo team is a guide inspired by The Twelve-Factor App (another great best practices guide you should read), it’s a really good starting point for understanding how to approach your GraphQL application with experience from the field.

The cool thing about opinionated software is that you don’t have to waste your time formulating your own opinion and arguing about it with your colleagues, often solutions for your problem have already been considered.

3. Be careful when introducing a new technology

If you’re considering introducing your company to GraphQL, or any disruptive technology for that matter, you should be careful about your approach.

I worked on a large application where older developers were working with younger developers ranging in ability from beginner to expert. The company had invested a lot into a REST-based system with an ES5 JavaScript client, the system had interfaces for literally hundreds of clients.

This code ‘worked’ (kind of, after some work) but was problematic from the start mainly because it was written using a circa 2005 syntax and there was only 1 specialist who knew the system inside out.

This old-style of code was preferred by the older developers, and they were reluctant to change it. The argument was that the system ‘worked’ and when you’ve made a significant investment, it’s generally a good idea to extend your code rather than rewrite it. There is a point where refactoring is necessary but even then, that can be hard to justify. JavaScript is the most popular language in the world. The easy argument, or so I thought… getting my team to switch to modern JavaScript took years. The influence of these senior developers was very strong.

I had been reading about GraphQL for some time and realized it was an appropriate solution for our problems, it provided a solid foundation for approaching security on an API gateway, it also provided an approach to solve over-fetching. It also brought a host of other less tangible benefits; documentation, data standardization, end to end typing, etc.

The lesson I learned, is that although GraphQL is a great technology and can indeed be the correct solution, many people are afraid of change and others will get offended if you try to change their work. Don’t forget that if you introduce new technology, you will be held responsible for it… You can make arguments regarding documentation and on-boarding but you can still step on toes without realizing it.

…maybe 50% of the developers I’ve met don’t like change, kinda matches the rest of the population. I don’t recommend that attitude, and I don’t think that practice will go far but this is still a factor to contend with if you’re working at a large organization, especially if your upper management could have been perceived to have made a bad decision or the company had made a significant investment already.

… be careful when introducing GraphQL, prove your points with data, make sure that QA is testing the system properly before renovation so that you can compare with what you’re repairing… use a Git history analyzer to help identify code hotspots, identify key problem areas to target.

Try to make sure that introducing GraphQL is perceived as an enhancement rather than a replacement… remember that although fellow developers appreciate refactoring, upper management tends to frown upon it (note: periodic refactors are a good thing), they tend to care more about customer-facing features and just arguing for higher productivity isn’t going to be enough. Perception is everything.

Make sure you have data to prove your case and be wary of passive-aggressive colleagues, for whatever reason, whether it’s insecurity or fear of the unknown, they can make your job miserable.

If your company is unwilling to change after you’ve made a good case, ask yourself whether you can accept the developer experience you have, some companies will embrace your attitude and are open to modern technologies especially when they present new solutions… working with dated systems can indeed hold your career back and prevent you from making progress in a timely manner, but you don’t want friction with your colleagues, especially managers.

Consider the fact that your company may not care about modernizing your skills for fear of training you to move on, bespoke systems built with legacy skills are a great way to lock someone into a company.

4. Pick the right tools for the job

OK, so now that you’re suitably convinced that it’s [possibly] OK to introduce GraphQL to your company, what framework do you use? how do you decide?

Picking the right framework depends on your application, and whether you need something in house or something that is managed. If you’re using a serverless architecture you will probably be looking at managed GraphQL services like AWS AppSync or Prisma Cloud. Managed services have one key downside, they are less customizable.

The most popular GraphQL framework is Apollo. It is used by Airbnb, Twitch, The New York Times, KLM and Medium.

Apollo is one of my favorite projects, the team understands the importance of adoption, you need users to use your product.. you need developers to get on the same page, you need contributors. Apollo has made significant moves to ensure large companies adopt GraphQL and use it in production. They have excellent documentation and a great YouTube channel.

Apollo is a full-featured GraphQL framework and provides excellent client-side tools for state management, they have open source components but also closed sourced enterprise services, they do not provide any database layer, you have to add your own ORM, a lot of users find the added boilerplate for database connections cumbersome. Several alternative frameworks automatically add database functionality.

Object-Relational Mapping (ORM) is a technique that lets you query and manipulate data from a database using an object-oriented paradigm.

Prisma intends to replace traditional ORMs using GraphQL as the interface, this can make database access extremely simple. CRUD operations are exposed via the GraphQL API and Prisma glues together the GraphQL server and the database

Hasura is an open-source engine that connects to your databases & micro-services and instantly gives you a production-ready GraphQL API.

Both Prisma and Hasura are Postgres based and both support webhook triggers on database events.

One key difference between Hasura and Prisma is that Hasura provides GraphQL to your front-end whereas Prisma is a GraphQL ORM for your GraphQL servers. You can use Apollo Server with Prisma. Hasura has some nice scaling features, both Apollo and Hasura have support for federation/schema stitching with similar implementations.

I enjoy working with Apollo because I can customize it but I have to add my own ORM, usually Sequelize or TypeORM, these mean a lot of repetitive boilerplate code, it’s also difficult to negotiate a source of truth.

Warthog is a new framework that has a code first approach to schema generation, you write familiar TypeORM models (with all the power of TypeORM) and Warthog CLI generates your GraphQL schema and resolvers for you. This allow you to focus on one clear source of truth, your code. It’s enterprise friendly being written in TypeScript. You also get free CRUD, which saves a lot of time.

Warthog is an opinionated framework with strong conventions, it generates clean, approachable code, but you can easily write modifications and migrate data in complex ways… in many ways, Warthog is the best of both worlds because you get access to your code to modify as you see fit, whilst having a lot of work done for you. It is a great example of what you can do with GraphQL and code generation.

5. Be prepared

Figure out the source of truth early on. There are 2 main approaches to GraphQL development, schema-first, and code-first . It’s important to grok the differences before you start developing. If you’re collaborating with various front end and back end teams, it is advised by Apollo to approach schema-first . This means making schema design the highest priority. Code-first (also sometimes called resolver-first) is a process where the GraphQL schema is implemented programmatically. Warthog and Prisma both advocate the code-first approach as it reduces bloat and tooling needed.

There are 2 main approaches to GraphQL development, and . It’s important to grok the differences before you start developing. If you’re collaborating with various front end and back end teams, it is advised by Apollo to approach . This means making schema design the highest priority. (also sometimes called resolver-first) is a process where the GraphQL schema is implemented programmatically. Warthog and Prisma both advocate the code-first approach as it reduces bloat and tooling needed. Don’t try to build the perfect schema. This is important. Principled GraphQL talks about using an agile approach to schema development. GraphQL offers such an aesthetically pleasing, functional data graph that it is very tempting to make the “perfect” schema, especially when moving from REST… but in my experience, this can be a very time-consuming process and will inevitably take longer than you expect, develop incrementally in an agile manner.

This is important. Principled GraphQL talks about using an agile approach to schema development. GraphQL offers such an aesthetically pleasing, functional data graph that it is very tempting to make the “perfect” schema, especially when moving from REST… but in my experience, this can be a very time-consuming process and will inevitably take longer than you expect, develop incrementally in an agile manner. Federation/Schema Stitching implementations are incomplete. The dream of GraphQL graphs is to bring different graphs to be “stitched” together into single “federated” graphs. There are some concerns with the approach of putting everything into a single graph, there are lingering monolithic tendencies and subscription support is not available. I’m confident these issues will be resolved but it does seem to be a difficult problem.

The dream of GraphQL graphs is to bring different graphs to be “stitched” together into single “federated” graphs. There are some concerns with the approach of putting everything into a single graph, there are lingering monolithic tendencies and subscription support is not available. I’m confident these issues will be resolved but it does seem to be a difficult problem. Avoid polymorphism . Coming from REST, you may be tempted to overload your types and re-create over-fetching scenarios. One important property of GraphQL is that a particular field must always return the same type. GraphQL fields can return a union of several object types, use unions to provide the same kind of functionality.

. Coming from REST, you may be tempted to overload your types and re-create over-fetching scenarios. One important property of GraphQL is that a particular field must always return the same type. GraphQL fields can return a union of several object types, use unions to provide the same kind of functionality. Don’t forget about abstract modeling. Coming from traditional REST and ORM systems, you may be tempted to map your GraphQL models to database models, but it’s important to remember your fields can be used to represent more abstract things, take for example a ‘me’ field which returns the current logged in user.

Coming from traditional REST and ORM systems, you may be tempted to map your GraphQL models to database models, but it’s important to remember your fields can be used to represent more abstract things, take for example a ‘me’ field which returns the current logged in user. Use Typescript and use code generation. TypeScript has blown up in the enterprise space, it reduces bugs, and adds intelligence + documentation to your code. GraphQL and TypeScript go very well together, but you should use a code generator to auto-generate your types and other snippets. There are different generators to try: GraphQL Code Generator, TypeGraphQL, and Apollo code-gen.

TypeScript has blown up in the enterprise space, it reduces bugs, and adds intelligence + documentation to your code. GraphQL and TypeScript go very well together, but you should use a code generator to auto-generate your types and other snippets. There are different generators to try: GraphQL Code Generator, TypeGraphQL, and Apollo code-gen. Watch out for request overhead. GraphQL adds overhead to requests because every request does run-time type checking and sub-selection. Different packages are more or less optimized, if you’re loading up a lot of requests and have large queries, you could be impacted. GraphQL applications notoriously suffer from the N+1 problem, which is beyond the scope of this article but it is effectively an issue where queries execute extra queries for records returned, there are various solutions but this is something you should be aware of.

Conclusion

GraphQL is an amazing technology and you should consider using it. I hope this article was helpful, thank you for reading and good luck with your project!

Resources:

Frameworks: Apollo / Warthog / Hasuru / Prisma / AWS AppSync

ORMs: TypeORM / Sequelize

Code generators: GraphQL Code Generator / TypeGraphQL / Apollo Tools

First Principles

The GraphQL Foundation

Apollo on YouTube

TypeScript

Principled GraphQL

The Twelve-Factor App