4th February 2022
How daily.dev significantly improved GraphQL performance using Mercurius
With Node.js 12’s deprecation from the LTS maintenance cycle looming in April 2022, developers are responding to the urgency in upgrading. Time is of the essence, with odd-numbered Node.js releases becoming unsupported six months after they are published, while even-numbered ones move into Long-Term Support (LTS) status for roughly two and a half years.
For daily.dev, a popular feed aggregator for developer news, the upgrading journey presented unique challenges. To start with, their current stack is still running on Fastify 2, which is already at its third major release with version 4 scheduled for release in the near future, while also still running Apollo Server 2. However, simply upgrading Node.js to the current release (16) turned out to break an essential Apollo Server 2 feature.
While migrating to Apollo Server 3 seemed like the obvious choice for Daily.dev, they decided to follow a new path.
In our recent webinar with Matteo Collina, Ido Shamun, founder of daily.dev talks about how migrating to Apollo Server 3 ended up being too time consuming, especially when it came time to integrate with their subscription engine of choice.
Ido decided to try Mercurius, a Fastify plugin sponsored by NearForm which offers the same core features he needed. In his own words, “the migration to Mercurius was super fast”, with minimal dependency and configuration changes needed to get it working.
Getting up and running on Mercurius was all that was needed to instantly see a significant performance increase. Ido doubled down on it and enhanced the setup with the addition of mercurius-js/cache, a Mercurius plugin that automates caching of queries.
The result was a significant improvement in latency and the overall number of transactions needed to complete requests, as seen in the graph below:
A Quick Dive Into Mercurius
There’s hardly anything that Mercurius can’t do when it comes to running a GraphQL server. As pointed out by Matteo in our webinar, one of the key things Mercurius handles for you out of the box is automatically compiling your queries into runtime code for maximum efficiency, through the use of a JIT (Just-In-Time) compiler called graphql-jit.
Aside from automatic caching provided through a plugin, Mercurius also takes care of integrating to data loaders to avoid 1 + N queries. It also includes support for Subscriptions, Federation, batched queries and custom persisted queries.
If you want to get your hands on some source code quickly, read on!
Mercurius makes it extremely easy to register GraphQL schemas and schema resolvers, functions that you can actually execute through your GraphQL queries.
In the snippet below, we have included some boilerplate code for instantiating a new Fastify server and registering the Mercurius plugin.
Notice how we set both schema, a raw string with your GraphQL type and method definitions, and resolvers, a list of the associated functions to run when running your GraphQL queries against those types.
Here, we see a Fastify route set to respond with the results of a call to its internal GraphQL server set up by Mercurius. This can drastically reduce the cost of maintaining API endpoints by just employing proper versioning and focusing on evolving your data and GraphQL types associated with it, rather than the mechanics of how data is retrieved.
Once seen by many as an overengineered approach to data fetching, GraphQL’s advantages over large systems that are constantly evolving and changing are hard to question.
As seen in daily.dev’s experience, adopting GraphQL with the right tooling can provide significant improvements to developer experience running complex APIs.
If you’re looking to maximize GraphQL performance on Node.js, Mercurius is a safe, reliable and extremely powerful option to consider.