GraphQL experiences from using it at scale (2 Part Series)
I recently wrote about my experiences with large scale GraphQL at C More. Since I am sold on the concept of GraphQL, I have been thinking about how I would approach implementing it in a another brownfield project – all over again. So these are my tips to anyone looking into implementing GraphQL in a brownfield project.
Of course this only applies if you are working in a larger organization, but I think the first step should be to get other developers excited.
As developers we often have the power to actually make things happen, and if you are like me, you work a lot harder and faster when you are excited about something. If you have developers in other teams who are excited and advocates for GraphQL, you are more likely to have success in your implementation.
Don't start by writing code! It will become very easy to repeat some of the mistakes I mentioned in my earlier post. Start instead by mapping out the data needs of the clients, and in what way it makes most sense for that data to be connected.
What should the root queries be, and what is better suited to be a field on another type? What should be an interface and what should be a union? What should the mutations return; will it be possible to resolve all mutated data from that response? I realize this might be extremely hard without experience with GraphQL, but do your best. Don't think too much about what the backend APIs are like when designing the schema, I think that GraphQL should be all about making it easy for the clients.
I'm not suggesting that you run this like a waterfall project, but in my experience a mistake in design is far more costly than taking a day to really get to know your domain and how GraphQL fits into it.
It is tempting to implement the core features of your product right away with GraphQL. However, those are the most painful parts to get wrong – and you will get things wrong. Instead, find some feature which won't be too connected to the rest of the graph. Implement it all the way and out to production, hopefully across different clients.
This will give you insights which will be valuable when you implement the more important parts. You will start to get get answers to questions like;
- Did you even like GraphQL?
- How did your hosting solution work for you?
- Do you need caching on the GraphQL server?
- What should the caching strategy look like (HTTP, CDN, in-memory, Redis, normalize data or not)?
- Were you happy with how you did error handling?
As I said, you will get things wrong. It is a lot better to detect a mistake after implementing it once or twice rather than 20 or 30 times. In my experience, bad patterns have a way of multiplying once they are in a code base. More junior developers will see existing code as a template on how to implement features, and the mistakes will spread.
As to how you correct the mistakes – note that GraphQL is unversioned 😱. You need to create a new field with a new name in order to make breaking changes to that field (remember to talk to other teams to learn what is breaking changes for them). It is tempting to try to come up with an even better name than last time, but when you are creating the fourth synonym in the same schema it's starting to feel silly.
What I feel is the more pragmatic and logical naming convention is to just append "Two" or "2" after the name. The clients can alias this field in their query to keep the old name in their code. Once no one is using the original name, you can deprecate the "Two"-version and go back to the original name with the new type definitions. The migration for the clients should hopefully be to just remove the alias at that point. Using the append-number naming convention hopefully makes it obvious why there are two very similar fields – the first one had mistakes in it.
Keep at it – implement all new features with GraphQL and use potential downtime to move old features to GraphQL.
It is also a good idea to have some monitoring of your GraphQL server. What queries are slow, why? Which queries and fields are being used, and by which clients? Make sure all clients send some metadata about who they are like version numbers and platform name. Find a product which solves this for your GraphQL server, or create your own.
I have not mentioned any specific technology here – and that is because I don't think it really matters that much. I suggest you use whatever library seems best supported in a language which won't be an obstacle in itself.