1

I would like to know the best practice for designing a REST API for a resource that has a has_many relationship with another resource.

In my app, companies have many technologies, and technologies belong to many companies. In the frontend, I want to render companies and their technologies.

I want to implement /companies endpoint so that it responds with companies and the technologies that belong to them. Then I can make a single API call to get all data necessary to render the page:

[
  {
    company_name: '',
    technologies: [
      {
        tech_name: '',
        tech_icon_name: ''
      },
      {
        ...
      },
      ...
    ]
  },
  {
    ...
  }
]

Is this a good practice, and what are the alternatives?

  • 2
    It's ok to use it this way. Super correct would be a nested endpoint like /company/#id/technologies. But this would come with high performance problems for larger lists and more complex code for the frontend. For similar problems I have used calls that took an include= attribute where the client could select which additional data would be added. – thorsten müller Aug 7 '16 at 5:47
  • It's fine and necessary in many cases for performance and ease of development on the client side. You should read on: HATEOS which allows you to add in the links to the real technology resources. Also interesting to read is techblog.netflix.com/2012/07/… which shows that you can even have differences in which data you include on for example a per device base. Depending on the data actually needed. You can do this per device but also per app for example if you have say a management and a consumer app. – Luc Franken Aug 7 '16 at 12:21
4

There's absolutely nothing wrong with returning nested arrays in the JSON response from a REST API, however, there's a question whether you want to do that.

If you are creating the REST API for one client, there's a great chance you want to return the technologies along with the companies, because your client has probably asked you to do so. Maybe they require the data and do not want to be querying your REST API multiple times. In that case it's completely reasonable to return the technologies along with the companies.

On the other hand, when you are creating a REST API which may be consumed by anyone you usually want to do some statistical analysis on the data you're going to supply and design your endpoints accordingly.

After your analysis you could find out the following: Your API is called by your clients 500 000 times a day. Each request takes on average 230 ms to complete, that is 31.94 hours of server time. You have talked to your clients and out of the half a milion request only 30 000 requests make use of the technologies of companies.

Because you are returning both (companies and technologies) at the same time, the other 470 000 requests are running slower and putting heavier load on your server than they ideally could. The query returns data which the consumers do not need at all and the data needs to be somehow processed and sent to the consumers anyway.

After thinking it through, you could make it so the technologies are retrieved on request and not automatically for all companies and the 30 000 consumers actually requiring the technologies would query your API a second time.

Thanks to the optimization, you can now query companies without the technologies on average in 195 ms and the average time for requesting technologies for a company separately is 170 ms. You still have to call the companies endpoint half a milion times, which will now take you 27.083 hours of server time and then process additional 30 000 requests for the consumers making use of technologies, taking 1.416 hour of server time, making in total 28,5 hours of server time.

By separating the queries, your system can not only better handle the load by reducing the load from 31.94 hours of server time to 28.5 hours, but your clients are also happier, because they get their information faster.

  • 2
    Upvoted your answer. I would also add that smaller resources are more easily "cacheable" than biggest ones. Thus reducing the load on server. – AilurusFulgens Aug 7 '16 at 10:44
  • Your examples with numbers are very helpful. If I separate two resources, I think I should return technology_ids: [...] in for companies so that they can be queried separately by the app. How do you feel about that approach and are there alternatives? – Sung Cho Aug 7 '16 at 11:20
  • 2
    @SungWonCho I actually really like the suggestion thorsten müller made as a comment, to completely ignore the technologies in the request for companies and have the companies/{companyId}/technologies endpoint instead. But you need to be careful when designing the endpoint. It all comes down to the requirements and needs of the consumers. Your API should be performant enough to cover the needs of the consumers, but shouldn't be killing your servers because of that either. – Andy Aug 7 '16 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.