I had an interesting conversation with some colleagues around resource design that I thought would be helpful to share.
The starting point was a simple question:
Should price generation be a HTTP POST or HTTP GET?
There’s solid reasoning for either of them. Let’s start with HTTP GET.
From a consumer’s perspective, a GET probably seems very intuitive. For how most people think about prices, it’s static information, so why wouldn’t it just be an attribute included on a GET of some other resource, like a Product, right?
For the purposes of this conversation, however, price is something that is computed at the time of the request. In other words, some supporting static information exists (like list price), but the actual “price” charged to the customer is dependent on other contextual parameters. Cases where this exists are the end price you pay at Amazon after taking into account shipping preferences, account status (e.g. Prime member?) or the price you pay when you buy a car. These prices are determined on the fly and may only be good for a limited amount of time, because the contextual information is subject to change. Hopefully, you can also see that “price” is actually a complicated piece of information.
Is HTTP POST beginning to sound better? Where this fits very well is that the “Price” is really a custom resource generated for that particular context. The customer, even though they may use the phrase “get me a price,” is really saying, “generate me a quote.” At this point, we’re creating a new resource.
But there’s one more thing. What if price calculation is expensive? If I make this a POST and generate this every time, won’t my costs go through the roof? Well, they don’t have to. There’s no reason that a subsequent POST with the same data can’t return a resource from cache in this scenario. In reality, you are probably updating the expiration date of the resource, so POST still makes sense. Furthermore, if you provide a unique ID for the calculated price resource, HTTP GET can be used to retrieve it again, it just shouldn’t update the expiration policy.
So, out of this, I came up with the following guiding principles on deciding whether calculated/derived data should be its own resource:
- Can the data stand on its own? That’s always a question for any resource.
- Does the calculation require contextual data from the consumer to perform the calculation, or are all the parameters already part of the potential parent resource?
- Is there value in keeping the calculated data around for some time to avoid re-calculation?
Hopefully these guiding principles will help you out. If you have other suggestions on factors that help this design decision, please feel free to share in comments or via your own blog post.