How can I handle many-to-many relationships in a RESTful API?

Make a separate set of /memberships/ resources.

  1. REST is about making evolvable systems if nothing else. At this moment, you may only care that a given player is on a given team, but at some point in the future, you will want to annotate that relationship with more data: how long they’ve been on that team, who referred them to that team, who their coach is/was while on that team, etc etc.
  2. REST depends on caching for efficiency, which requires some consideration for cache atomicity and invalidation. If you POST a new entity to /teams/3/players/ that list will be invalidated, but you don’t want the alternate URL /players/5/teams/ to remain cached. Yes, different caches will have copies of each list with different ages, and there’s not much we can do about that, but we can at least minimize the confusion for the user POST’ing the update by limiting the number of entities we need to invalidate in their client’s local cache to one and only one at /memberships/98745 (see Helland’s discussion of “alternate indices” in Life beyond Distributed Transactions for a more detailed discussion).
  3. You could implement the above 2 points by simply choosing /players/5/teams or /teams/3/players (but not both). Let’s assume the former. At some point, however, you will want to reserve /players/5/teams/ for a list of current memberships, and yet be able to refer to past memberships somewhere. Make /players/5/memberships/ a list of hyperlinks to /memberships/{id}/ resources, and then you can add /players/5/past_memberships/ when you like, without having to break everyone’s bookmarks for the individual membership resources. This is a general concept; I’m sure you can imagine other similar futures which are more applicable to your specific case.

Leave a Comment