DEV Community

Versioning in APIs

Dave Cridland on April 12, 2019

It's Christmas Eve, in 1991. All around the world, children are reaching fever pitch in excitement. Many adults are brimming with enthusiasm too. ...
Collapse
 
zakwillis profile image
zakwillis

Hi Dave, trying to understand this.

Are you stating that the endpoint, depending upon versions should be;
/shoppingbasket/user/v1/fred (original)
/shoppingbasket/user/v2/fred (this json/DTO object may have more attributes).
? I think you are.

Thinking of this in .Net Core/.Net Web API, these are separate endpoints and they have to be because they are returning different objects. Like Martin says, seems like double the pain but I get your idea.

I have seen certain APIs do something like this (JIRA)
server/version/shoppingbasket/fred

This makes sense as you could maintain separate code bases but simply deploy the URL without screwing up the routing. In your client request, the base URL can be configured. Clients know what they are signing up for.

Anyway, interesting thoughts.

Collapse
 
dwd profile image
Dave Cridland

I'm really saying you don't want to do v2. Have /shoppingbasket/user/fred return an object, and the caller be forgiving about new attributes. If you need truly breaking changes, then you do need a v2, but it's a last resort and an indication you've broken something.

HTTP (or at least REST) doesn't make this sort of thing easy.

Collapse
 
zakwillis profile image
zakwillis

Hi Dave, I thought about this some more. It makes sense. Automappers can be strict or optimistic, so they can rigidly enforce a data structure in the client.

My main concern with your approach is;

  • We are assuming no fields/substructures are ever removed. A protocol is simply a common set of rules for communication. The parts of speech can be part of a protocol toolkit and can never be removed. In the data based example, the data is not a protocol - it is subject to change, can see fields removed. In our day and age, we are becoming ever sensitive to risk upset to others and are constantly changing policies etc.

What might have to happen, is the protocol (endpoint in your system) delivers simply a validation object and a version object. This tells the client what it has to conform to. There could be an additional validation end point. This is quite neat because it lets the validator end point say which formats it conforms to?

REST is itself, a protocol, yet the packets are unknown to the protocol. A bit like a pipe doesn't care what is shoved down it, as long as it fits. Plumbers know that a soil pipe is a protocol, a mains pipe provides water - they don't test what goes through it when they connect a toilet or a tap. A manufacturer can quite rightly say, the dishwasher was never designed to run on the waste pipe protocol.

Collapse
 
zakwillis profile image
zakwillis

Understood Dave. Will think about it some more. Thanks.

Collapse
 
martinhaeusler profile image
Martin Häusler

An interesting take on the problem. As a server-side developer, supporting two versions of an API that are actually different (breaking changes) is very difficult. Twice the number of endpoints, twice the number of DTOs, twice the bugs, twice the headache... Breaking changes also mean potentially very little source code sharing between the two versions; translating to twice the maintenance effort too. The argument "if you ever do a /v2 then it's already a different endpoint" really struck home for me. Gonna have to think about that some more.

Collapse
 
sebbdk profile image
Sebastian Vargr • Edited

This is why i like the GraphQL API format.

The client say i want Y in X shape, and the server complies if it can.

That way the server adapts, to whatever the clients wants instead of the other way around.

Furthermore incompatibilities only occur if the server stops supporting whatever shape the client is requesting, and even better the API url can stay the same.

Collapse
 
hectorlf_86 profile image
Héctor López

"These are very useful and effective for software library versioning, and there's a temptation to assume that this model works well for protocols too.

It does not."

I believe this is something you only realize when you've gone through and suffered from it. Guilty.

Collapse
 
dwd profile image
Dave Cridland

Pretty much every major protocol and API has tried to do this. MIME has its fixed header field. XMPP has 'version="1.0"' dutifully exchanged between every peer, every time. HTTP was standardized at 1.1 only to distinguish it from the (rather borked) 1.0. Even IMAP went through a series of versioned revisions (though later versions are themselves actually capabilities), and Mark was one of the first to identify this as a problem.

If you're only seeing this in hindsight, you're in really good company.

Collapse
 
tonymet profile image
Tony Metzidis

great review. how do you feel JS has handled versioning e.g. ES5, ES6 ?

Collapse
 
ziarv profile image
Zia

Good explanation