A couple of years ago, we at the engineering team at Secfi decided to go GraphQL. This helped us reduce complexity in our system, improve performance and have a more intuitive API. Let's talk about that!
Our decision to start using GraphQL was a response to some specific problems we had. So let's start by giving some context about our system, and what those problems were.
At that point in time, our frontend was made up of a couple of different clients. And as we kept adding features to them, it got clear that they had different needs, data consumption wise. Some of those needs were difficult to fulfill given our backend capacities.
Our backend was designed as a distributed system. In it, different services written in Node and Python exposed their own REST APIs. Each API allowed clients to interact with the subset of models the service was responsible for. Some of our models were related to one another, although living separately and being manipulated by different services. This created a clear pain point: joining and working with data coming from multiple services.
As we initially lacked a strategy to fix this on the backend side, logic to operate around it was written in the clients. In these cases, the client would need to call the server multiple times, collecting data from different services. When everything was fetched, it could be joined and used. This was slow and introduced too much unnecessary complexity to the frontend. We identified our first, big need: to simplify our clients.
But having a distributed system came with another drawback for us, data management wise. The APIs of the multiple services tended to be slightly different as they were written using various frameworks and languages. This also added extra complexity to the clients, which needed to be able to interact with the server in multiple ways. Moreover, it made working around the system less intuitive.
To sum up, our data strategy was causing us these problems:
- The frontend was getting complex.
- The frontend was getting slow.
- Fetching data was not intuitive.
The problem was clearly identified now. We needed to rethink our data strategy. The solution had to come from tweaking our distributed system, not from punishing our clients any more.
One of the ways we figured could potentially improve the situation, was to start using the facade pattern. This software pattern was introduced in the Gang of Four's prominent book Design Patterns, and using it we expected to move the complexity that our data model had brought to the clients away from them. This complexity wouldn't disappear, but would be treated by a new service (the facade), focused on concentrating and minimizing it.
Now that we had decided on the facade pattern, GraphQL started to look like part of the ideal solution. This is because GraphQL is designed to get many resources in a single request, and that was exactly what we wanted to allow our clients to do. The new facade service would then be a GraphQL server, using the aggregate of all our different models as a schema.
Our new GraphQL server, acting as a facade, also dissipated the problem we had with the backend not being intuitive. This is because we could now always be served by the facade when requesting any data. There is no more need to talk to different services, in different ways. Now designing new services was more friendly, as choosing new frameworks or simply API designs was not a problem in the frontend.
After having used the facade pattern and GraphQL for a while, we can say we are happy with the results. The refactor was expensive, but our original problems have been mitigated:
- Complexity was effectively reduced in the frontend. The developer experience is now nicer, and adding features is faster.
- Performance was improved. Most data management happens now on the server side, reducing communication times.
- Our API got to be more intuitive and easier to interact with. Also, we can now check the auto-generated Docs offered by Apollo Server's GraphQL Playground. Pretty cool!
We want to keep stepping up our GraphQL game, of course! Some of the initiatives we are discussing or already working on are:
- Federating our services. This aims at improving separation of concerns across our backend. You can read more about federation here.
- Using DataLoader. As our product scales up, we are working to improve the platform's performance. The DataLoader library is one of the solutions we are considering.
Does this sound like fun to you? If so, we may be a good match. 🥰
Consider checking our open positions at secfi.com/careers.