Is REST APIs versioning necessary?

Not applicable

If API 's new versions are backward compatible,then is versioning APIs necessary in the url?

Cant we have the same API url for all the future changes as well and make sure the APIs are backward compatible?So,this helps for consumer's perspective as well, as he need not make his code changes aligning with API for its every version changes.

Whats the strategy behind versioning APIs?

7 14 2,429
14 REPLIES 14

@RK4

Versioning is not necessary, it is a best practice.

Now there are two aspects to your question 1) Is versioning necessary 2) Is versioning necessary to happen in URL.

The short answer to both is No, it is not necessary BUT YES , it is a BEST practice. Let me explain a bit:

"If API 's new versions are backward compatible" - so this the bedrock of your argument. Unfortunately I don't think you can predict what your requirement will be 5 years down the road. If you have a successful API then it may last many many years and you may be forced to do non-backward compatible changes.

So for future proofing it is always good practice to version your API.

Now there are many ways to version to API.

a) Via URL

b) In headers: So I can have a customer header called Version and specify the version number there.

c) Query param: Similar to headers. I can specify the version in a query param.

So the question becomes why URL?

- Its mainly because of visibility. If I am a developer who is on the consuming end of the API and the API is versioned in Header I may simply miss it. But if it is baked right in the URL then I will never miss the info.

- Clarity - If I have an API like this: http://baseUrl/v1/users. It very clearly states that the Users resource is at version 1. Because I may have different resources at different versions. Like http://baseUrl/v2/products. So someone looking at it will understand that resource products is at version 2 and resource users is at version 1.

You will find more help here: http://apigee.com/about/blog/technology/restful-api-design-tips-versioning

Not applicable

@sartak gives an answer that many agree with, but you will not find any consensus on the topic. My personal view is that versioning in APIs is neither useful nor necessary in most cases, and I don't put versioning in mine. Versioning is only useful if you think you will offer version1 and version2 concurrently for the same entity, which seems logical but in fact most people never do. I also have a strong dislike for versioning in URLs, because it obscures identity and causes problems with links. Imagine that you have a resource /v2/xxxxx and within it you want to provide a link to the resource yyyyy. Should you link to /v1/yyyyy or /v2/yyyyy? Does yyyyy even have a V2? If you think about it for a while, you will conclude that you actually need n+1 URLs per entity: one for yyyyy itself, and one each for the versions of it. IMO, this is a mess.

As I said, you will find no consensus on whether or not to do versioning, and if so, how to do it. You will have to make up your own mind. Which way you lean may depend on how attached you are to the fundamental REST model where entities have strong identities, and URIs can be used for links. The advice that @sartak gave may be good advice for the sort of APIs you design, but for the ones I like to design it would not work well.

Hi @RK4 great question!

It largely depends on your actual use-case as to whether explicit versioning is a good idea or not. How frequently would you have new versions of APIs. And you've already indicated that you are maintaining backward compatibility. In that case there is no obvious requirement for versioning.

That said, I think there are at least two aspects to consider for versioning - the consumption side and the maintenance side.

The consumption side as you have already indicated would prefer not to have to make any updates as new versions of the API are released because this is a cost to them and if they are not going to be using any new features then there is no benefit to them of the new version.

However, there could be a consequential impact on the maintenance side of taking this approach - your API code could become complex in order to support multiple pervious versions seamlessly. Over time you may find that you make sub-optimal implementation choices or you compromise the experience of the new features in order to maintain that backwards compatibility. Alongside this, it's likely that your maintenance costs would be increasing as the number of backward compatible APIs were increasing, so you may want to be able to stop supporting the older code and even drop the older code at some point.

If you use explicit versioning in your basepath then you would maintain backwards compatibility by explicitly publishing the versioned basepaths and independently maintaining the code that supports those versioned basepaths. E.g. you publish /v1/flights. Then you update, so you publish /v2/flights but you continue to maintain /v1/flights. And so on as you release new versions. This way, your API consumers who are using /v1/flights do not have to change.

If your API is becoming more complex and you're starting to have the impact I talked about earlier, then the advantage of explicit versioning is that you can introduce an explicit API deprecation strategy; e.g. you publish that you will only maintain backwards compatibility for 5 versions. Your API consumers have some period of stability and when the time comes to deprecate a version you just simply drop whichever version it was and the associated code.

The disadvantages are that you have more work to do in publishing and getting folks to use your new API versions. Maintaining separate code bases or branches could become challenging too, especially if you are making lots of rapid changes. Also, if you are rolling out many versions and not able to support all of them, you would be forcing change on your API consumers at a faster rate that they would like.

There's a potential hybrid model here, where behind the scenes you maintain explicit versioning in your APIs but then you publish via a non-versioned basepath and you do cname updates to point your non-versioned basepath to whatever actual API version is your current live version. This model could offer a couple of advantages, but describing it in words is a little hard so I'll do a worked example here:

You publish flights.mytravelco but behind the scenes you cname that to /v1/flights.

Over time you roll out a series of updates that were backwards compatible, so now you have flights.mytravelco pointing to /v4/flights. Your API consumers haven't noticed anything because they continue to use flights.mytravelco.

At this point you realize you will not be able to maintain backwards compatibility. So first, you keep flights.mytravelco pointing to /v4/flights but you publish /v5/flights to early adopters. Once you've stabilized the new API, you announce that the existing API is being deprecated, anyone who doesn't want to use the new one needs to update their app to point to /v4/flights (because shortly you're going to update flights.mytravelco to point at /v5/flights). Then comes cutover, so you continue to support two specific versions, but you've made it clear to your consumers that v4 is deprecated and will be going away. And then once an appropriate amount of time has passed, you fully deprecate v4 and stop serving requests on it.

Anyway, these are broad theoretical scenarios, I'm looking forwards to others relaying practical experiences and hopefully you will get a well rounded set of views to help you decide what is best for you.

Not applicable

Hi @RK4

As posted by @sarthak this exact question is answered at

http://apigee.com/about/blog/technology/restful-api-design-tips-versioning

I agree with @sarthak's comments about future proofing. The idea that you can guarantee today that your api won't require a breaking version change in 5+ years is a dangerous gamble.

There's a couple of things to unpack here:

1) if you create your urls with the format /v1/sales/account, and 5 years later your initial guess was right - you've made no breaking version changes - your url is still /v1/sales/account. What have you lost?

Trying to retrofit versioning into a published api, though, is painful for you and your customers.

2) don't forget that your api url is the representation of a resource. It isn't the resource itself. In other words, it's an abstraction layer that hides the system level details of your implementation. So you can happily implement non-breaking changes behind the scenes via multiple internal versions, and still keep the api version as version 1. You would only change the api version when it becomes very clear you need to.

Not applicable

This is a nice article about API versioning and about the different ways you can do this, and mainly - there is no single "right" way to do it :).

http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html

Thanks for sharing @Ivan Novakov! Which approach you have used in the past? How did that work for you?

Not applicable

@RK4 I warned you that there would be no consensus 🙂 @charlesc states the conventional wisdom and the Troy Hunt blog elaborates on it. Let me offer a few thoughts to further confuse you.

The idea of versioning in an API rests on the assumption that it is common that I have a change I want to make to a resource that cannot be made in a compatible way, and that supporting V1 and V2 of the same resource concurrently will solve the issue. The problem is that most interesting API objects are read/write, and for this strategy to work, updates in V1 have to reflect in V2 and vice/versa where the data is common, updates to V2 where the data is unique to V2 must be possible without breaking V1, and updates to V1 that ignore the new properties of V2 must also be OK. The number of cases where this works is actually quite small, which is why most APIs never evolve past V1. So this versioning strategy generally fails to deliver on the future-proofing that people hope for, and worse, versioning in URLs makes it almost impossible to use hyperlinks, which I value highly. Putting versioning in headers is compatible with hyperlinking, but it mostly jut adds complexity without actually solving any problem—maybe it will work for some read-only resources.

If conventional wisdom on future-proofing via API versioning doesn't work, what are the alternatives? Here is the strategy I use:

  • Don't put versioning in the API
  • Document what backward compatibility means. The most important thing that clients should be tolerant of is extra properties showing up in resources. Test for this—have the server add a few random properties occasionally in resources. That way clients know they are playing by the rules before they are deployed.
  • Don't use PUT for update, use PATCH. PUT requires clients to round-trip properties they were not coded to recognize, which they are likely to get wrong. PATCH allows the server to preserve all properties that are not explicitly modified. (Some people use the PUT method, but implement the semantics of PATCH—don't do this. PUT means full replacement.)

Contrary to what @charlesc said, it is easy to add versioning later if you follow my advice and decide in the future that it doesn't work for your API.

If you think I'm a lone crazy who is out of step with everyone else, google "roy fielding api versioning".

@charlesc makes another misstatement. An URL is not a representation of a resource, it is an identifier (and locator) of a resource (the I in URI is for identifier). The representation of the resource is the body you get back when you do a GET on its URL.

Not applicable

So,Can this be like...

API with multiple versions internally.And APIGEE proxy always exposes same /v1/xyz url to consumer.

I am taking this hint from @charlesc...Will this be good?Or can this be also having some cons?

Answers above approach the definition of versioning in terms of data and representation. My view is that versioning is to guard applications from all backwards incompatible changes to the same resource - and this definition also includes behaviour.

One example: Apigee analytics APIs returns all records it finds today based on your query/filters if you don't provide any pagination parameters yourself. Assume you write a schedule job that executes a query to this API, get all results and process them daily. What happens if one day Apigee realises that returning all records is too computation/IO intensive and decides to impose a default page size for all queries, e.g. 50. Your job will continue to execute with no errors as resource representations are same. Data in/out are same. Headers are same, etc. But your processing results will not accurate any more as you don't have the full dataset.

This scenario can also be used as an example to demonstrate that sometimes it is hard to recognise a backwards incompatible change until its too late - it may not be as easy as "json response is different". Therefore it is necessary to include such checks in your QA pipeline.

Assuming you decide to version your API, the whole concept is much more complicated than where to store the version number in the request. Developer community communication and notification of versions, parallel execution/hosting of APIs, collecting accurate analytics to report # of applications using version x are more 'real-world' and challenging.

My view is that versioning is quite useful if/when you need it and causes no harm at all if you never have to use it. Making backwards compatible changes is what everybody likes/wants but sometimes circumstances might dictate otherwise. I also don't think you can confidently make assertions on whether you will make any backwards-incompatible changes to your API in the future or not. So the safest bet, in my opinion, is to go with versioning. You count yourself lucky if it stays at v1 for 10 years.

Do you have to version? The short answer is no, API versioning is not necessary. This is largely a discussion with your teams about managing change in your APIs.

Cant we have the same API url for all the future changes as well and make sure the APIs are backward compatible? YES!

I've seen appropriate uses for both versioned and non-versioned APIs. I've also seen the misuse. Generally speaking as a practice I tend to follow the non versioned model. The reason for this is that it causes the API development teams to focus on the design without the option of being able to *break* it later. In my experience, the quality of the design is improved since the discussions of not being backward compatible are treated with a higher level of severity as they should be.

This is equally debatable, but I'm also a fan of versioning the platform as a whole rather than individual services. Fair points are made by @sarthak @charlesc @oseymen and I highly agree that you can not predict the future of your APIs. I also believe that as technology and our methods of consumption for it change, we need to take what still works then redesign into the next platform of services. The thought here is that if you have the right focus on your design, you will not only have a clear idea of what needs to change in the future, but making that change will have considerable value and so an incentive to use. It could also be mentioned about the monetary benefits in versioning the platform as a whole, but that’s another topic.

All said, I have absolutely no problem versioning from the get-go for services that are expected to have frequent breaking changes as a part of the design and do not require significant developer community shift.

Not applicable

My assertion is still that traditional versioning does not help future-proof your API—at least for read/write APIs—it only gives a false illusion of helping. Several of you have disagreed—maybe you are right. It should be easy to test whether or not you are right. All we need is a single example that disproves my assertion. We need a detailed API—either real or made up—and a similarly detailed change that we are going to make to it. We can reason through how the change would work with and without versioning. In order to be helpful, the example has to be detailed and specific—generalities won't help. I will send a T-shirt to whoever presents the best example. Do we have any volunteers?

Not applicable

In general, I'm more in favor of not versioning APIs. However, I think the ultimate answer is again "it depends". Here are my reasons why:

  1. Maintainability and fragmentation. Having a single API is by many factors easier to maintain than multiple versions of your API. I've seen many organizations in "version hell", trying to patch the same bug in multiple places, because the codebase has become fragmented by multiple versions.
  2. Avoid Confusion. With multiple API versions consumer apps of your API will need to learn where is what, so there's no longer a single point of truth. If they need a new feature, they'll have multiple places to look for it. And for developers, imagine maintaining and publishing multiple documents of the same API.
  3. Your API can still evolve without API versioning. In my experience, with good API design principles upfront in 80% of the cases. Changes required to support the evolution of your API can be isolated internally without impacting your clients. Remember, most breaking changes are mostly about breaking the contract with consumers apps. This is the part that you need to be most careful about. Therefore, my recommendation is not to jump immediately writing code without much forethought of your APIs. Design the resources of your API first, then build. Get started with a framework from OpenAPI Specification. Believe me, it will pay off in the long run.
  4. Write Consumer Apps and APIs that are tolerant. If you need to introduce breaking changes, your Consumer Apps and APIs can be written in ways that they can still handle breaking changes. If you know upfront that something is going to change the contract, ask yourself, is there a way to implement in a way that I can handle both scenarios? in many cases you can. For instance, the concept of Tolerant Readers, have been out there as software engineering best practice for quite a while.
  5. Last but not least, how mature is your organization in terms of software engineering best practices? Not versioning APIs requires though discipline to build your API, in which you can test the entire lifecycle of your API before releasing it. Most organizations, aiming to achieve this state start their journey with Continuous Integration with the ultimate goal of Continuous Delivery. There are plenty of tools out there from Apigee that can help you to get started with this. Take a look at My talk on Continuous Integration - The Virtuous Cycle at I Love APIs 2015 and Hands-on Lab from my colleague @rakeshapi.

Good luck!

Former Community Member
Not applicable

I'll throw my hat in the ring for the t-shirt and present my experiences with API modelling.

There are two schools of thought expressed there:

1: Versioning is best practice. It can be done via URL, Header or even query param.

2: Versioning is not necessary

My most recent experience from modelling APIs came from my previous job. Let me describe some of the design decisions we had to make.

1: Do we need to have API versions?

We defaulted to - “yes”. That is how we have always done SOAP services. Didn’t see reason to change now. Also, Google, PayPal, etc. did it. So why not us? Lastly, perhaps most importantly, I can think of many services where the major versions running in production were backward incompatible. New capabilities/products are frequently added. I’d say that in the 2-3 year period is it not uncommon to have at least 2 major versions for most services. So why keep the older version? Well, mostly because of economics. It serves existing consumers well (i.e., they get what they need from those services). There is no money to rewrite those consumers to consume the new services. From a consumer’s point of view, there is no business value to point to a new version when they can meet their business needs with the older one.

NOTE: All data is from SOAP services.

2: How do we construct the URL and where do we put the version?

https://{fqdn}/{apiVersion}/{apiResourceName}/{resourcePath}?{parameters}

FQDN - The fully qualified domain name for the API. In production "api.xxx.com" is used and the lower environments will have environment specific FQDNs.

API Resource Name - The name of the API (Ex: Customer, DepositAccount etc).

Version number – The major version of the API, always starts with 'v'. Beta versions of the API will include the "beta" suffix (Ex."v2beta").

Resource Path – A predefined list of business entities available under the API resource name.

Parameters – A list of conditions/criteria/fields to access the resource in the resource path.

I also subscribe to the point of view that the resource should not contain verbs. As with all things, there are some exceptions to this rule (perhaps that is not relevant to this discussion).

Since we decided to put a version to the APIs, we agreed it makes sense to version the resource just before the name appears (as is conventionally done by most APIs). On the face of it, that looks like a great idea. But this gives rise to some problems also. Let me explain with an example. In banking, you have the notion of P-A-E aka Party-Agreement-Events.

Party (An Individual or a Business - an entity that has a relationship with the bank. A customer is a type of party)

Agreement (colloquially known as account)

Event (specifically, financial events, colloquially known as transactions)

Problem #1: APIs with Entity Relationships:

So, should we allow for an API like this? /v1/parties/123/agreements/456/financialevents/789?

(i.e., fetch the transaction id 789 that belongs to an account 456 that belongs to a party 123). Where do you stop? One can drill down further. How many levels do you support? Also, who will build this API? Party, each type of an agreement and financial events are owned by completely different business units (and rightly so). Even if we get through the org hurdles, when such a linking occurs, what version of the agreements API and financial events APIs should you link to? What if we determined some mechanism to link them and the individual API owners made a backward incompatible change (without telling the Party API owners)?

NOTE: OData has some interesting ideas by supporting $expands. With hindsight, I would’ve given OData more consideration.

Problem #2: Returning links/URLs in responses:

One of the most popular APIs at a retail bank will be: /parties/123/agreements

In this case, we decided that this API call would describe the relationship between the resource party and the resource agreement. It is expected this particular API will return the financial portfolio (account details) owned by the customer.

I remember the first iteration of the design of this API where we had to deal with the fact that although “agreement” was a good abstraction, it was difficult to return any meaningful data back. Different “agreement” types don’t share a lot of data in common. You’d think that every agreement should have an ID and BALANCE - right? Maybe for ID, but that’s not true for balance. Also, what does balance mean? For a credit card, BALANCE is the amount you owe. For a deposit account, it the amount bank owes you. Then it gets more complicated. BALANCE doesn’t tell you the freshness of data. You have overnight balance, available balance, outstanding balance, balance that takes pending transactions (like cheques, stop cheques, wire transfers etc.) into consideration and many others factors. It depends on the type of agreement you are dealing with.

Heck, some agreements don’t even have transactions. Like Term Deposits. So what did we do? Well, we have to specialize the abstraction type (agreement). That json returned by the API could look like:

{"agreements": [{"id":124,"type": "creditcardagreement”"Ownership": "primary","availableBalance":12345,"URL":"http://bank.api.com/v1/creditcardagreements/124"},{"id":345,"type": "mortgageAgreement","Ownership": "joint","principalOwing":40000,"URL":"http://bank.api.com/v1/mortgageagreements/124"}]}

NOTE: As a consumer, I had to parse the “type” field because depending on the type, my subsequent API call will be completely different. Also, not every array element was identical. It was a denormalized object that had describe a minimum set of useful elements of a particular account type.

Then we hit the problem Martin Nally described here in the same community post:

"I also have a strong dislike for versioning in URLs, because it obscures identity and causes problems with links. Imagine that you have a resource /v2/xxxxx and within it you want to provide a link to the resource yyyyy. Should you link to /v1/yyyyy or /v2/yyyyy? Does yyyyy even have a V2?"

How would the Parties API team know what version of Credit Card API or Mortgage API to return? Ok. Let's drop that portion then. How about this?

{"agreements": [{"id":124,“type”: “creditcardagreement”"availableBalance":12345,"URL":"/creditcardagreements/124"},{"id":345,“type”: “mortgageAgreement”"principalOwing":40000,"URL":"/mortgageagreements/124"}]}

Says nothing about the version or where the API is hosted. Seemed to work in theory, at least at first glance. Then we asked the question, how is this information helping a consumer? The consumer still has to figure out the version and the endpoint where the API is hosted.

Lastly, perhaps most importantly, where is the Parties API team getting this information (about links to other resources) from? I think this is one of the biggest problems of linking resources. What is the source of the link? The Parties API team cannot source this information from a system of record (like it does with all other fields). It requires design time knowledge. We cannot expect them to hard code it (or for this team to constantly be aware of where all the other Apis are hosted).

Eventually, we dropped the field all together. Makes you wonder why would you want to version APIs.

On one hand, I definitely see the benefits of versioning - esp. in an enterprise where you have many teams and requirements and features are constantly changing. Complicating it is the fact that consumers don’t want to change often.

On the other hand, there are a lot of problems if you do version and see the APIs in your organization as linkable resources.

What did we end up doing?

We did not allow for links to be returned in the payload except for two specific use cases:

1: Process/workflow APIs - because the next ‘action’ is determined by the first API you called

2: Pagination

In both cases, the returned links are from the same system. So there are no version problems.

We use versions for resources (ex: /v1/parties) and did NOT allow for linking of resources through URI (ex: /v1/parties/12/3/agreements/456 would not be allowed). Relationship would be implemented (ex: /v1/parties/agreements), but they do not link to other resources. Also,

GET https://api.xxx.com/v1/abc/123/xyz (related xyz,sub-resource) 

is NOT same as

GET https://api.xxx.com/v1/xyz (top-level resource)

Hiding versions from consumers:

Service Abstraction (through interface and location abstraction) is one of the tenets of SOA and generally implemented by ESBs. APIs, in my opinion, claim neither. It is expected a consumer knows where the service is. It is expected a consumer can choose which (valid) version of the API they want.

How did SOAP Services do versioning? Well, they use namespaces that usually contained a date or version in it. JSON/API has no equivalent standard to my knowledge.

2 years ago i gave a presentation Slides . One way of doing this