For the last 5 years I have worked a lot in the REST area designing, creating and/or maintaining Web APIs. Mostly in .NET Core but also APIs built on .NET Framework. In my opinion, REST is a very solid architectural style, that proved its worth over a longer period and over differently sized projects. Working with REST for some years, however, did bring some frustrations to the surface, especially when it comes to designing and developing the consumers of a REST service (mostly using Angular in my case). That’s the reason why over the last few months I have started to learn more about “alternatives” like GraphQL. And I have to admit I am cautiously excited about what GraphQL brings to the table even in the .NET ecosystem.
This article will be a general overview, or summary, of different aspects of GraphQL that I’ve learned during the last couple of months by reading, attending conferences and trying some things out. Just to make it clear, I am not a GraphQL expert or guru, but I just like do document my learning points in articles, as they might be useful for others too.
Talking about GraphQL in the .NET ecosystem is not very easy since there is one common misconception that I encountered all over the places. In a funnier note, this misconception would sound something like “GraphQL is like OData, only different”. So let’s see why this is not really true.
GraphQL vs. OData
OData isn’t new at all. Besides the very technical definitions, OData is, from my point of view, a query language put on top of REST resources. This is nothing bad per se, since OData provides capabilities for sorting, filtering, querying and reducing fields in the output of REST APIs. This solves the problem of overfetching or underfetching data. There are, however, some potential problems OData might cause:
- By opening up an OData endpoint, you lose control of what your clients are able to do and you don’t have explicit queries or use cases tracked.
- It URI centric. What this means is that it essentially doesn’t resolve the frustrations I have with REST. It just makes them sweater 🙂
For more insights into OData from the trenches I recommend you Jeff Hendley’s article.
Developed internally at Facebook in 2012, before public release in 2015, GraphQL is a data query language that provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need, makes it easier to evolve APIs over time and enables powerful developer tools.
GraphQL implements resolvers that fulfill specific graph queries—the client cannot ask for anything the server does not explicitly handle (huge advantage over ODATA). The server returns only what the client asked for. No more, no less. No wasted bits over the wire. Furthermore, everything sits behind one single GraphQL endpoint, so we’re outside the REST model. Again, I don’t say that this is good or bad; I say it might be useful in some scenarios!
GraphQL in the .NET ecosystem
When it comes to GraphQL in the .NET ecosystem there are two libraries to chose from: GraphQL.NET and Hot Chocolate. As stated a few paragraphs above, it’s not really easy to chose, as both libraries implement the latest GraphQL spec (June 2018) and both are feature rich. Based documentation comparison and trying to get started with both of them, HotChoclate is the one I’d chose.
The main reason for that is that Hot Chocolate seems to provide the far better performance. In this case I think that performance does really matter. Why? Because with GraphQL you basically add a new layer between the UI and the domain and as we know each added layer comes with an increase of execution time. That’s why, if I chose to add this additional GraphQL layer to may system, I prefer to be confident that it is as fast as possible.
Another reason is that Hot Choclate provides some features that aren’t present in GraphQL.NET, like schema stitching. Schema stitching is the capability to merge multiple GraphQL schemas into one schema that can be queried. Why is this useful? Just imagine we have lots of specialized services that serve data for specific problem domains. Some of these services might be GraphQL services, others might be REST services and, sadly, some of them might be SOAP services. Hot Chocolate schema stitching provides a way to create a gateway that bundles all those services into one GraphQL schema. That’s a scenario I’m sure you’ll encounter a lot in services-oriented systems and therefore this feature might come in handy.
Let’s however focus a little bit on performance!
Hot Chocolate performance advantages
A fundamental part of both Hot Chocolate and GraphQL.NET is the lexer and the parser. And that’s where the performance boost comes in. The Hot Chocolate lexer does not allocate any extra memory to do its work. All allocations are done on the stack which means that we produce less work for the garbage collector. This, in turn, means that it will also have a lower execution time. Here are two screen shots that show the difference:
The parser is a little bit different. It still allocates some memory since it produces a syntax tree. This syntax tree is still needed for backwards compatibility. But the parser itself is a ref struct and lives on the stack. So, all the parser state is allocated also on the stack and is gone after the execution has finished. Here are some screenshots just to have an idea what a big difference this makes.
Plans going forward
I am working right now on a side project for which I’ll surely use Hot Chocolate since the entire project could benefit of all the advantages that GraphQL brings to the table. This means that I’ll play around a lot with GraphQL and Hot Chocolate in the coming months and therefore my plan is to keep documenting on my blog what I am doing with GraphQL, both with advatages and disadvantages, If you are interested, you might want to check back from time to time, as I’ll most probably encounter a lot of different challenges on the way.
How useful was this post?
Click on a star to rate it!
Average rating / 5. Vote count:
Latest posts by Dan Patrascu-Baba (see all)
- Configuration and environments in ASP.NET Core - 25/11/2019
- GraphQL in the .NET ecosystem - 19/11/2019
- A common use case of delegating handlers in ASP.NET API - 12/11/2019