API Versioning

220 views
Skip to first unread message

Doug Swanson

unread,
Apr 17, 2012, 5:17:52 PM4/17/12
to API Craft
Do you version the API or each service individually?

In other words if you have:

/v1/x
/v1/y

and y changes in such a way that would break consumers using it you
end up with

/v1/y (temporarily for backwards compatibility)
/v2/y

The question is do you also now have

/v2/x

even if x hasn't changed?

I think the answer is yes but I don't have a great reason why outside
of that it's easier for users of the API to use one base URL including
the version number.

Maybe someone who has given this more deep thought can help me see the
light.

Thanks.
Doug

Scott Regan

unread,
Apr 17, 2012, 5:19:16 PM4/17/12
to api-...@googlegroups.com
i am totally losing it -it's not on my calendar, can you resend?
i hope it's a Gmail bug and not a sign of my aging!

Daniel Roop

unread,
Apr 17, 2012, 6:40:10 PM4/17/12
to api-...@googlegroups.com
Versioning is a fun topic.  Here is how I think about it.  There are 3 types of versions and each is managed differently.

Resource version: this is when you are changing your resource model.  An example would be taking a single guest profile call and splitting into two calls.  For this you just create new URLs.  You can do that with a path segment. But the key here is the concept has changed.

Representation version: this is when the resource model stays the same but the way you present it changes.  This could be moving from XML to json. Or a new structure within one of those formats.

API version: this is useful for bundling feature sets for clients. It mostly affects your entry points and I would use the style you recommended below.

We tend to favor resource versioning and while we haven't needed it representation versioning over API versioning.  This may be because of our particular situation, but using these two strategies, along with defining backwards compatibility expectations (namely adding properties is not incompatible so clients are expected to deal with this). Allows us to avoid versions in the URL for the most part. 

The main reason why we avoid them in the URL is because once you do get to Hypermedia Based APIs it becomes very difficult to manage.  Imagine a situation where you had a service the exposed catalog content, and another service that exposed reservation details.  You could imagine the reservation resource would point to the catalog content service.  That seems fine, but now imagine you interact with a third service that exposes an itinerary.  If the itinerary service links to v2 of the catalog content, you are putting an unnecessary burden on the client of these services to understand multiple catalog versions.

If the two Services (reservation and itinerary) did point to different "concepts" that would make sense, but if they were just pointing to "restaurant" information there is no reason they should point two different resources. If the client dealt with two different representations, this would be transmitted in the accept header allowing the client to only care about one representation of a restaurant.

Peter Monks

unread,
Apr 17, 2012, 6:19:38 PM4/17/12
to api-...@googlegroups.com
G'day Doug,

With one exception, we do the latter - a version is for the entire API, regardless of how little or how much it differs from the previous version (obviously we do some "clever tricks" to ensure we get code reuse, where appropriate, across versions).

The one exception is that we'll be providing multiple "APIs", which are functionally cohesive groups of otherwise independent resources, for example something like:

cmis
rm
dam
wcm

(these are all content management acronyms - apologies if it's not very clear as to why these would be functionally distinct groupings)

Not saying it's the only or even the best way of doing things, but so far it seems to be working out ok.

Cheers,
Peter

 

 


On Apr 17, 2012, at 2:17 PM, Doug Swanson wrote:

Jack Repenning

unread,
Apr 17, 2012, 6:52:44 PM4/17/12
to api-...@googlegroups.com

On Apr 17, 2012, at 3:40 PM, Daniel Roop wrote:

Versioning is a fun topic.  Here is how I think about it.  There are 3 types of versions and each is managed differently.

Isn't there a fourth class? The most compelling story I've seen for API versioning is changes in the required business context logic, such as changing the required authentication method.

Say you start out with a roll-your-own, in-band "POST /1/session" with credentials in the body.

Then the business decides to require http BasicAuthentication instead. You can't just add that requirement, you'll break existing users. So you transition, defining version 2

  GET /2/resource

with implicit BA, leaving version 1 with home-brew auth in place for a while, warning  your partners, and tracking who's still using version 1 so you can nag them.

Jack Repenning




Daniel Roop

unread,
Apr 17, 2012, 7:40:08 PM4/17/12
to api-...@googlegroups.com

I would have included that under API version, since it is a breaking change to the entire API.

However if you use the authorization header or any header really for this stuff you can allow all kinds of methods without breaking the API.  You would only need to version if you put the auth somewhere in the body.

mca

unread,
Apr 17, 2012, 11:18:45 PM4/17/12
to api-...@googlegroups.com
I do not use version information in my HTTP API work at all. I've been
building and supporting Web APIs for more than a decade and this has
not been a problem.

I have a current client that has been using the same "base" API for
more than seven years and has evolved their offerings quite a bit over
that time and we've never had to add version numbers to the API URIs
and have not had problems "breaking" any existing clients in all that
time.

yes, the front-end *app* has undergone version numbers (this is
marketing versioning, tho), but the application interface has not.
yes, our URIs change when needed, but this is not a "version change",
this is a "resource change"
yes, *sometimes* a digit shows up in a URI, but there is no "version
management" invovled here, it's just a new resource URI
yes, we often make minor modifications to a response representations
for and existing URI (add elements, for example) but they are done so
that existing clients are not adversely affected.

I have a client w/ a library of more than 600 "API" resources which
they use to create multiple "applications" for hundreds of enterprise
clients serving thousands of users. They have dozens of "third-party"
client applications (usually internal apps built by partners or
"first-level" clients) anf they have no problem working w/ us or
maintaining their existing code when we make changes to the libraries.

I just don't version.

mca
http://amundsen.com/blog/
http://twitter.com@mamund
http://mamund.com/foaf.rdf#me

Mike Kelly

unread,
Apr 18, 2012, 5:23:32 AM4/18/12
to api-...@googlegroups.com
Are you saying that a 'new version' of some set of resources is just a
new set of resources in your system?

--
Mike

http://twitter.com/mikekelly85
http://github.com/mikekelly
http://linkedin.com/in/mikekelly123

mca

unread,
Apr 18, 2012, 5:26:09 AM4/18/12
to api-...@googlegroups.com
general pattern is:
1) extend the existing resource whenever possible
2) if you cannot extend it, add a new URI

IME, it turns out quite a few of the minor changes can be handled by #1, too.

Mike Kelly

unread,
Apr 18, 2012, 5:29:13 AM4/18/12
to api-...@googlegroups.com
Ok, I second this approach - but how is this not versioning?

mca

unread,
Apr 18, 2012, 5:30:31 AM4/18/12
to api-...@googlegroups.com
guess it depends on your use of the word.
our representations do not contain version information
our URIs do not contain version information

Jørn Wildt

unread,
Apr 18, 2012, 5:31:02 AM4/18/12
to api-...@googlegroups.com
Yes, Mike A. you are most probably aware of the hypermedia-web discussion going on here: https://groups.google.com/d/msg/hypermedia-web/LdKfi47QCxw/ZSICQtXqvy4J :-)

Could be nice to get some input/experience from a large deployment like yours.

Enjoy your conferences :-)

/Jørn

Mike Kelly

unread,
Apr 18, 2012, 5:34:34 AM4/18/12
to api-...@googlegroups.com
but there is some affordance (link relation?) in your app which
provides two paths, one of which is meant to supersede the other?

mca

unread,
Apr 18, 2012, 5:45:27 AM4/18/12
to api-...@googlegroups.com
i'll use a current example client i am working with....

the identifiers (usually @rel, sometimes something else) are usually
stable, even when the resource evolves. this sometimes happen even if
the URI changes (esp. for web browser cases where the bindings are in
JS that is also provided by the same origin).

in this implementation, a multi-tenant approach is used. each customer
has a unique URI namespace (via DNS - customer1.myapp.com). in that
case, some of the resources are "customized" based on the DNS. for
eample, the rel="invoice" for customer1.myapp.com might return a
representation that is an "incompatible extension" of the
rel="invoice" representation of customer2.myapp.com. in this case,
it's a diff URI in the path between customer1 and customer2

not sure if that helps/answers your Q, sorry.

Jack Repenning

unread,
Apr 18, 2012, 2:49:08 PM4/18/12
to api-...@googlegroups.com
On Apr 18, 2012, at 2:29 AM, Mike Kelly wrote:

> Ok, I second this approach - but how is this not versioning?

There's an important difference, here, between designing an API that will be served by only one server, and designing an API that will be implemented by many independent parties.

If there is only one instance, then we can be confident that all changes seen by the client evolve monotonically. That is, under the change doctrine just mentioned, if a client connects at time "A" and sees that the result includes field "X", then the client can be confident that a connection at time "B" (later than "A") will also include "X". Maybe some other stuff too, but definitely "X".

However, if many implementations of the API will exist (as for example with an API that becomes a standard), they may not all update at the same time. So, when a client connects at "A" and sees "X", there's no assurance at time "B" that "X" will still be there -- if the connections at "A" and "B" are to different implementations. It's possible that the server connected to at time "B" implements an earlier version of the API, one before the invention of "X".

In a way, we can say that time itself is the versioning system in the first case, but that it's insufficient in the second. If you're doing the second case, you may have to be more rigorous and explicit about your versioning.

To answer the quoted question: in a first-case (single implementation) world, a certain class of changes is "backwards-compatible," and we don't need any overt versioning to handle it. But in the second case (multiple implementations), even these changes require overt versioning.

Jack Repenning

Mike Kelly

unread,
Apr 19, 2012, 3:29:25 AM4/19/12
to api-...@googlegroups.com
Right, I understood the point - I've been using this approach for a
while. Fwiw, it seems simpler to describe it is as; non-breaking
changes don't need a version change but breaking changes do.

My problem here is that this is still versioning, it's just a strategy
that keeps explicit version changes to a minimum but doesn't eliminate
them completely. Referring to it as 'not versioning' is confusing and
misleading. That does not mean it is not a good strategy for m2m
applications.

Cheers,
Mike

Jack Repenning

unread,
Apr 19, 2012, 12:44:08 PM4/19/12
to api-...@googlegroups.com

On Apr 19, 2012, at 12:29 AM, Mike Kelly wrote:

> My problem here is that this is still versioning, it's just a strategy
> that keeps explicit version changes to a minimum but doesn't eliminate
> them completely. Referring to it as 'not versioning' is confusing and
> misleading.

Hmmm ... how about "(not) making the versioning explicit in the URL and/or media"?

Jack Repenning

Reply all
Reply to author
Forward
0 new messages