Search code examples
node.jsgraphqlquery-optimizationtheorybandwidth

Optimizing GraphQL queries by including fields only if they hold a value?


I have no idea if this is a good idea at all, really bad practice, so that's what I'd like to know.

Say I have a graphql server, which sends back stuff like this:

[

    {
      name: "John"
      age: 55
      isSingle: false
      hasChildren: false
      lovesMusic: false #imagine more fields like these
    {,
     # ...loads of records of the same format here

]

Say the file is large and there are lots of records: Wouldn't it be a good idea to just strip it off the values that are false and only send something back whenever isSingle / hasChildren / lovesMusic is true, in order to save on bandwidth? Or is this a bad idea, making everything prone to error?

So in this example, I'd just send back:

[

    {
      name: "John"
      age: 55 
    {,
    ...

]

I am worried because I have large graphql objects coming back from my queries, and lots of it is just fields that aren't filled out and that I thus won't need in my frontend.


Solution

  • To my understanding The whole point of GraphQL is to receive exactly the specified set of types and fields - not more, not less.

    Altering the results with some middle ware or deleting fields containing 0, null, false or undefined would be the violation of Graphql Specification. There's no point in using some kind of convention if you are going to violate it anyways.

    Neverthless there are some options to consider for performance and bandwidth optimization:

    using shorter names

    you could use shorter field names in GraphQL schema. you could even come up with some kind of compression algorithm of your own. For example you could replace logical names with characters and then map them back to regular names on the front-end.

    {
         name: "John"
         age: 55
         isSingle: false
         hasChildren: false
         lovesMusic: false
    {
    

    would become something like this:

    {
         n: "John"
         a: 55
         s: f
         hC: f
         lM: f
    }
    

    then you could map the field names and values back on a front-end sacrificing some performance of course. You just need to have some dictionary object in javascript which stores shorter field names as key-s and longer ones as values:

    const adict = {
      "hC": "hasChildren",
      "lM": "lovesMusic",
      "n": "name",
      ...
    }
    

    Althrough this approach will shrink your data and save you some bandwidth, it is not the best practice application-wise. somehow I think it will make your code less flexible and less readable.

    external libraries

    there quite a few external libraries that could help you with reducing dataload. most popular ones being Message Pack and Protocol buffers. These are very efficient and cleverly built technologies, but researching and integrating them in your solution might take some time.