10

I am trying to build a rest API for an android app. Suppose I have a users table with (id, name, email) and a songs table with (id, song_name, album) and a rich join association between them as streams having (user_id, song_id, listen_count). I want to fetch details about all the streams and show it in the app as a list. The list would be showing the song name, album name, user name and listen count. I see three plausible options -

  1. GET to /streams and fetch a list of all the song_ids and user_ids. Then make GET to /user/:id and /song/:id for each user and song id to get the user and song information.
  2. GET to /streams and fetch a list of all the user_ids and song_ids. Then one GET to /user?ids=<comma_separated_ids> to fetch information about all the users and a GET to song?ids=<comma_separated_ids> to fetch information about all the songs.
  3. GET to /streams and fetch everything in one call. Something like -

    [
    
      {
    
        "user_id" : 10,
        "song_id" : 14,
        "listen_count" : 5,
        "user" : {
          "id"     : 10,
          "name"   : "bla", 
          "email"  : "bla",
        },
        "song" : {
          "id"     : 14,
          "name"   : "blu",
          "album"  : "blu"
       }
      },
    ...
    ]
    

I'm tempted to go with option 3 because it gives me everything in one call, but I don't think it's very rest-full and I fear that it won't be scalable. Option 2 is good but it takes 3 calls which would mean considerable time loading the list. And option 1 follows rest but will take numerous calls for showing the list and doing so many calls from a mobile device isn't feasible.

What would be the recommended way to go about this?

6
  • Rest-like and salable are two different things. Aug 28, 2015 at 6:34
  • @RobertHarvey how do you mean?
    – aandis
    Aug 28, 2015 at 6:37
  • What makes you think the quality of your REST interface affects the salability of a product? Are you actually selling the REST interface? If you aren't, nobody cares what's under the hood. See also meta.stackexchange.com/q/142353 Aug 28, 2015 at 6:44
  • 1
    There's singificant overhead in making a REST call. Consequently, there's a strong possibility that 3 is the best approach from a scalability standpoint, especially if you use all of the data so returned. Aug 28, 2015 at 6:51
  • 1
    Related in a way programmers.stackexchange.com/q/257408/56903 Aug 28, 2015 at 15:32

2 Answers 2

7

When creating a REST interface, there is no requirement, or even expectation, that the responses on the REST interface correspond directly to tables or joins in the database.

Your /streams interface can just as easily be represented as

[
  {
    "listen_count" : 5,
    "user" : {
      "href"     : "/users/10",
      "name"   : "bla", 
    },
    "song" : {
      "href"     : "/songs/14",
      "name"   : "blu",
      "album"  : "blu"
    }
  },
  ...
]

Where the JSON objects contain the main details of users and songs that are (nearly) always relevant for consumers of a stream resource, and a link to the relevant user/song resources if further details are needed.

This is essentially a variation of your third option, with a fallback to option 1 if more details are needed.

3
  • There is no guarranted answer to me folks... option 3 could be simple if the domains remains simple but it will get you in trouble for objects that beholds more than two levels of aggretations. For example, you want to retrieve all the avaiable Courses with of data of their teacher. You have Course -> Teacher (information about the person as a teacher, stored in a separeted table) -> Person (the physical person, as you can recall the same person could be a teacher of several Courses). Option 2 is scalable, and requires * request. Also opt. 1 is scalable too, but it could need >> request.
    – Victor
    Dec 6, 2017 at 15:00
  • So to synthethise the above comment: if you looking for efficiency, then strive for number 1, but if you looking for a system that could grow without problems in time (scalability) without giving headache, aim for option 1 or 2. It is worth to mention that premature optimiization is the root of evil... so this is warning to option 3.
    – Victor
    Dec 6, 2017 at 15:03
  • need to correct myself above.. "if you looking for efficiency, then strive for number 3"
    – Victor
    Dec 13, 2017 at 15:57
3

You definitely want a single GET operation that returns metadata about each song and user in addition to their opaque ids.

  • As you pointed out, it's much simpler. That is a good thing.
  • Making one of the most common operations for your client apps a single server request instead of O(n) requests is much more scalable. In the long run, the network will be your biggest bottleneck, so you don't want to send any more requests than you have to.
  • The ids by themselves are kinda useless except for making additional REST calls.
  • As long as your metadata has a relatively small and bounded size (e.g. no pages of descriptive text or actual audio files, just names, types, counts and so on) returning it in addition to the ids is unlikely to be a performance issue.
5
  • Interesting. But option 3 doesn't really adhere to a rest-full design does it? A GET to streams should return all the streams and nothing else(even if they are just ids and useless to the client).
    – aandis
    Aug 28, 2015 at 7:08
  • 3
    @zack In the strictest sense, yes, but any design principle can be taken too far. When you find yourself arguing the program should do something useless, that's usually not a good sign.
    – Ixrec
    Aug 28, 2015 at 7:17
  • Metadata is data about data, this is just data. Aug 28, 2015 at 9:57
  • @zack: A streams resource can logically contain (parts of) other resources. Things that are logically part of a resource should be present in the representation of that resource. Aug 28, 2015 at 11:55
  • 1
    @zack option 3 is completely 100% RESTful. The Resources you expose via your API have zero requirement to relate to anything else in your system, including your DB tables and your domain model. You could have 3 database tables and 600 resources if that made sense for your web app. There is no requirement to represent your DB relationships in your Resources relationships. Aug 28, 2015 at 16:00

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.