Versioning web services
Freshness Warning
This blog post is over 18 years old. It's possible that the information you read below isn't current and the links no longer work.
14 Feb 2006
When I add a new feature to Tagyu’s web service API, how should I best version it? I don’t want to maintain and support multiple, old copies of the API, but I also need to ensure I don’t break backward compatibility. A change to the API can’t cause existing apps out there to stop working.
At first I thought this was an easy problem. I’d simply ensure that any time I made a change to the API the changes would be additive. I wouldn’t remove any data, I wouldn’t change the location of representation of the data, I’d only add new data. If a case came up where I needed to change how the XML data is stored, then I’d consider maintaining parallel versions of the API for a period of time. I’d figure out how to do that when the time came. Amazon Web Services inserts their API version into the URL, but that’s always seemed a bit clunky to me.
Today’s new API feature made me rethink how I change the API and represent different versions. It made me rethink what changes should be even considered as a new version. Today’s change involved the insertion of a couple of attributes to one of the XML tags. Shouldn’t be a problem right? That’s what I thought, too.
Before the change, the XML node for a suggested tag looked like this:
<tag>sometag</tag>
After the change, it looked like this:
<tag rel="related" href="http://tagyu.com/api/tag/sometag"> sometag </tag>
Those two new attributes broke some APi implementations, including my own software, the Tagyu Movable Type plugin. The plugin uses XML::Simple to parse the API’s response. And as far as XML::Simple is concerned, those two formats are completely different XML structures. XML simple represents the first one as this…
{ 'tag' => 'sometag' }
And the second as this …
{ 'tag' => { 'rel' => 'related', 'href' => 'http://tagyu.com/api/tag/sometag' 'content' => 'sometag' } }
The Tagyu plugin accesses the tag through $tags->{'tag'}
but under the new structure, that’s not the tag at all, it’s a hash that contains the tag, among other things.
The point of all this is that even though I thought I was being careful, today’s API change broke things. And that’s bad. It should never happen.
I’m looking for thoughts on how to version a web services API or really any software that’s delivered as a service. How do you prevent changes from having adverse effects while at the same time providing improvements. Is different API versions at different URLs really best or only way to go?