Versioning web services
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?