Chattines of REST APIs is one of the topic which came up in discussions with Viljami Kuosmanen about a year ago. I did not have time to put more thought on it before now. I kind of remember what Viljami said, but to make it clear what the hell that means, why develoopers (API consumers) do not like it and how it can be avoided, needed a little more thinking and exploring.

Chatty API

Chatty API is one that requires consumer to make tremendous (subjective matter) amount of distinct API calls to get needed information about a resource. George Reese has defined chatty API as any API that requires consumer to do more than a single call to perform a single, common operation. That sounds possibly a bit too rigid to be followed in real life but a good guideline. Common is context dependant and subjective matter.

Why chatty API is bad?

Reason why chatty APIs are considered poor quality is because requiring multiple network calls will slow down an application. This is because each call contains data overhead (i.e. sender information, headers, authentication) which will slow down an application as well as network latency per each request.

Netflix API redesign is one interesting and educational case to look at. Chattiness is not REST API only related issue. For example Microsoft writes about “Chatty I/O antipattern” in Azure context.

Practical example

For example if you need to collect resources for a section in web application and if API is chatty, it might force you to get needed info for each object separately. Luckily most of the REST APIs are not designed that poorly. That was just an extreme example. The chattiness is normally more subtle.

Lets’s take an example. Developer wants to get the product reviews, but API offers only GET method to list products (/api/products/123) and returns

{
   "name": "A monkey",
   "cost", "$5000.00",
   "reviews": [
        "/api/reviews/1",
        "/api/reviews/2",
        "/api/reviews/3"
        ...
        "/api/reviews/2071"
    ]
}

To get the reviews for a product, developer needs to make N amount of API requests to get the reviews. N might be thousands depending of the amount of the reviews. Eh, looks like a flaw in API design and that’s what it really is. You have just created prime example of a chatty API.

Use resource oriented approach

To avoid chattines in APIS, instead of building get and set methods in the API, you focus on resources. But regarding the example above, fix might be that API has /api/products/{id}/reviews endpoint. Then the consumer would get all reviews with one API call which could be limited and ordered with parameters.

{
   "name": "A monkey",
   "reviews":[
        { "id": "1", "reviewer": "Jarkko", "notes": "foobar"},
        { "id": "2", "reviewer": "Sven", "notes": "foobar"},
        { "id": "3", "reviewer": "Pirkko", "notes": "foobar"},
        { "id": "4", "reviewer": "Toni", "notes": "foobar"},
        ...
        { "id": "2071", "reviewer": "Pekka", "notes": "foobar"} 
    ]
}

API might take advantage of the partial response style too. /api/products/123/reviews?fields=notes. Then the consumer gets just the information s/he needs.

{
   "name": "A monkey",
   "reviews":[
        { "notes": "foobar"},
        { "notes": "foobar"},
        { "notes": "foobar"},
        { "notes": "foobar"},
        ...
        { "notes": "foobar"} 
    ]
}

HATEOAS may be the purists’ choice, but it does come with a certain amount of baggage. It makes an API more complex to implement while tending to bloat the response. It can give rise to a more “chatty” style of integration as clients navigate through links rather than jumping straight in to the resources they need.

Offering links to next set of responses (if paginated) is the common way to implement HATEOAS idea partially. Idea is that you offer the consumer ready constructed API endpoint calls in the response in addition to actual content data.

{
   "name": "A monkey",
   "reviews":[
        { "notes": "foobar"},
        { "notes": "foobar"},
        { "notes": "foobar"},
        { "notes": "foobar"},
        ...
        { "notes": "foobar"} 
    ],
    "links": [
      {
          "rel": "self",
          "href": "https://host.com/api/products/123/reviews?fields=notes&limit=30",
      },
      {
          "rel": "first",
          "href": "https://host.com/api/products/123/reviews?fields=notes&limit=30?from=0",
      },
      {
          "rel": "next",
          "href": "https://host.com/api/products/123/reviews?fields=notes&limit=30&from=30",
      }
  ]
}

If you don’t know in design phase…

Of course you can’t know every use case for the API in design phase. But you should know the most common use cases and fulfill the needs of those. You can follow how your API is used mostly, ask feedback and use cases from the API consumers and so on. Based on that feedback you add new endpoints to offer needed data with less amount of API calls to reduce chattiness and at the same time increase the developer experience.

Chunky APIs

The opposite of chatty APIs is chunky API. At least some of the scholars describe the difference of chunky / chatty API: “Chatty services tend to be ones that return simplified information and use more fine-grained operations. Chunky service tend to return complex hierarchies of information and use coarse operations. In other words, the difference is that chatty services require more calls than chunky services to return the same information but allow more flexibility to return only the information that is actually required.

To some extend I agree but for example “return only the information that is actually required” is something that can be achieved in chunky APIs with partial response discussed above.

Conclusions

Exactly like in most cases middle way is the right path to take. Your API should not be too “chunky” nor “chatty”. How to achieve the middle depends of the context and use cases. Your task as API provider is to fulfill the needs of the consumers as well as possible. You can’t fulfill all the needs, but you should focus on the most common use cases for your API. 80/20 probably is a good guideline here too. When you can fulfill the needs of 80% of the use cases, you’re on the strong side of winning the hearts of the developers.


Some more to read from 100 Days DX