Decrease load on your JSON APIs by using sparse fieldsets
In Leadfeeder we develop our frontend app in Ember.js backed by a Ruby on Rails JSON API. Personally I think it’s a great choice of stack as it lets developers quickly deliver new features without writing tons of code. However, no matter how cool and easy-to-use the stack is, in the course of time you’ll eventually have to face some performance problems.
In our case the problem was that when the frontend app grew we started having lots of views requiring different sets of attributes present in the same models. Of course in the beginning, when the number of model attributes was small, frontend component could simply fetch the record with all its attributes and just pick the required ones while rendering, but at some point it started getting out of control.
Let’s take a look at one of the examples. Rendering the following list requires only name
attribute from account
model:
However the backend would return a lot of other attributes alongside the name
:
Requesting for full models with attributes unnecessary at given moment makes the whole app naturally slower, especially because some of the attributes need to some heavier computations while preparing the response. This made me start searching for a way of getting just the data required for rendering the component…
The solution — sparse fieldsets
It turned out that somebody gave a thought to this problem already while designing the JSON API serialization format and called it “sparse fieldsets” (official description can be found here).
The name isn’t very catchy and self-explanatory, but in simple words it allows requesting for a defined subset of attributes in resources by adding fields
param to the URL.
So, coming back to the previous example with accounts list: with sparse fieldsets we are able to fetch the accounts with name
attribute only just by passing fields[account]=name
:
By the way a cool thing about sparse fieldsets is that you can also define subsets of attributes in included models. So for example if we’d like to render the company name alongside the account name we’d just need to slightly modify our url: app.leadfeeder.com/private-api/accounts?include[]=company&fields[account]=name&fields[company]=name
Rails implementation
This post explains how to use sparse fieldsets in Ruby on Rails applications with the most popular serialization gem: ActiveModel Serializers. I’m sure thought, that you can find sparse fieldsets functionality in other libraries as well.
Active Model Serializers introduced sparse fieldsets support back in 2015, so basically all you need to do is passing the fields
hash to the render
method in your controller. I suggest adding the following helper method in your base controller which you can reuse in child controllers. Feel free to use the snippet below in your projects:
Summary
I really recommend introducing sparse fieldsets in your Rails APIs, because, as I’ve shown in previous paragraphs, it is relatively easy to implement and gives you instant performance boost. Do it even if your application is still small maybe it’ll save you some headache later :)