8

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?

  • Rest-like and salable are two different things. – Robert Harvey Aug 28 '15 at 6:34
  • @RobertHarvey how do you mean? – aandis Aug 28 '15 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 – Robert Harvey Aug 28 '15 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. – Robert Harvey Aug 28 '15 at 6:51
  • 1
    Related in a way programmers.stackexchange.com/q/257408/56903 – toniedzwiedz Aug 28 '15 at 15:32
6

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.

  • 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 '17 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 '17 at 15:03
  • need to correct myself above.. "if you looking for efficiency, then strive for number 3" – Victor Dec 13 '17 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.
  • 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 '15 at 7:08
  • 2
    @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 '15 at 7:17
  • Metadata is data about data, this is just data. – Jacob Raihle Aug 28 '15 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. – Bart van Ingen Schenau Aug 28 '15 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. – Cormac Mulhall Aug 28 '15 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.