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 |
|
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:
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”:
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