No F*cking Idea

Common answer to everything

Versioning of Your Code and API

| Comments

People that deal with evolving applications in ‘the wild’ are often hit with quite a tricky question. How do you version your api and the code behind it? We had similar issue where I work and i will present my idea on the topic.

Motivation

Different clients requests features, you upgrade your codebase and mvoe along for example streamlining api. You need a way to version the code so old clients have time to move work on upgrade and new clients can use new api without having problems.

Restful API

This is the first part and its easy so i will be fast on this. In my opinion using subdomains/CNAM’es for versions like

v1., v2., v3.yourdomain.com or 20012013.yourdomain.com is the best way to handle changes in API from client side. As we spoke internally using headers or any other thing can make clients go mental because they are using other type of software and some change could be not trivial. Yes actually people have this type of problems with very old bash/perl systems.

But why subdomains are cool in my opinion will unroll in next section.

But what about the code ?

Most important thing is how easy it will be for developer to add things without breaking other things. Yes this is the problem! Most people will think that rolling a solution with some sort of scoping, inheritance is ok.

eg.

1
2
class V2::People
class V1::People

No its not. This is actually sh*t. Why ? Even with good code test coverage you still have issue becasue each of this class is using other classes basically sharing them. And changes in their code can affect other version of api. And with V1 and V2 it is managable but if you have 5-9 versions its starts to be crazy.

How to solve it ?

Imagine a queue of versions in form of deployed boxes.

My idea is very simple. You simply tag version codebase and deploy new version on new box while pointing new subdomain to new app.

What do you gain ?

  • You are sure you can deploy from 0 your app in production in isolated environment BIG WIN
  • You know you can upgrade OS/packages in your production app with each release BIG WIN
  • You know how many people are still on some version
  • Your developer can develop in new version just like in any other app without caring for compatibility issues

We live in age of cloud deploy so spinning new instance is not that expensive!

There is only one point you have to be very aware, that is data persistence. If you are using SQL you can only ADD COLUMNS/TABLEs never remove anything. But in most thing you will do exactly this anyway.

Version deploy’s on virtual machines example: Image of V'm boxes in the web

Ok that was fast lets recap it

Process! how would you implement this in real life ? Simple!

When you have an app and you deploy it using eg. puppet + capistrano. When you deploy first version you make a tag in git with name eg version-1 or 20032014-deploy and deploy it to a box assigning a CNAME.

Next you start working on new version and when you will get new version you tag it 21032014-deploy and deploy to a new box. This must contain “build whole box script” in puppet or if you are using docker. This way if you eg. added redis to stack you need to be sure your production deployment scripts are ready. This makes you be focused on keeping your “production ready setup” always up to date.

And after deploy you move along and work on new version. When you need to decomision old version you just kill the box. Also each version should be monitored how many requests it actually gets to the API because if you will have 20 versions up and some are getting 0 traffic you can kill them.

Example where many versions use same db “ring” / “cluster”: V'ms using DB

Rollback ?

How do you rollback ? simply checkout deployment tag and deploy :)

The gain ?

The gain in this strategy is isolation, if you need more boxes for your main version you have ready production scripts so all you have to do is to spin them and be sure that CNAME is load balanced.

Summary

I don’t think this strategy has any problem / hidden traps. You get smaller codebase to work with, ability to upgrade your production boxes and application libs/frameworks as you always move forward and deploy from scratch. You don’t do upgrade-production box deploy but fresh deploy. Also fresh deploy can be smoke-tested by tester before putting it into production. Deployment scripts makes you by default ready to scale your app horizontally.

Again What you do:

  • start: Deploy version to a fresh box
  • Upgrade Code/OS and add features
  • Tag new version
  • goto start:

IMHO everyone should move to this type of strategy in context of api versions.

Cheers – Jakub Oboza

Comments