So far in this blog series on Cloud Native we’ve said a lot of nice things about it being an effective approach, but "fine words butter no parsnips", as we used to say in the 17th century. Cool tech is not much use unless we can practically apply the concepts.
So in this post we're going to consider some ways of going cloud native-ish and ponder how even a blank slate is not actually blank.
A company of any size might start a project that appears to be an architectural blank slate. Hooray! Developers like blank slates. It’s a chance to do everything properly, not like those cowboys last time. A blank slate project is common for a start-up but a large enterprise can also be in this position.
However, even in a startup with no existing code base you still have legacy.
Legacy is not always a bad thing. It’s the abundance and reuse of our legacy that allows the software industry to move so quickly. For example, Linux is a code base that demonstrates some of the common pros and cons of legacy (including: it’s a decent OS and it's widely used but it’s bloated and hardly anyone can support it). We generally accept that the Linux pros outweigh the cons. One day we may change our minds but we haven't done so yet.
Using your valuable legacy might help you start faster but push you away from a Cloud Native approach. So, what do you do?
Consider the problems that Cloud Native is designed to solve: fast and iterative delivery, scale, and margin. Are any of these actually your most pressing problem? Right now they might not be. Cloud Native requires an investment in time and effort and that effort won’t pay off if neither speed (feature velocity), scale nor margin are your prime concern.
Imagine you are an enterprise with an existing monolithic product that with some minor tweaks and re-positioning could be suited to a completely new market. Your immediate problem is not iterative delivery (you can tweak your existing product fairly easily). Scale is not yet an issue and neither is margin (because you don’t yet know if the product will succeed). Your goal is to get a usable product live as quickly and cheaply as possible to assess interest.
Alternatively, you may be a start-up who could rapidly produce a monolithic proof-of-concept to test the market using a monolithic framework like Ruby on Rails with which your team is already familiar.
So, you potentially have two options:
In this case, the most low-risk initial strategy might be option 2, even if it is less fashionable and Cloud Nativey. If the product is successful then you can re-assess. If it fails, at least it did so quickly and you aren't too emotionally attached to it.
Imagine you chose to build the MVP monolith in thought experiment 1 and you rapidly discover that there’s a huge market for your new product. Your problem now is that the monolith won’t scale to support your potential customer base.
Oh no! You’re a total loser! You made a terrible mistake in your MVP architecture just like all those other short-termist cowboys! Walking the plank is too good for you!
As a result of the very successful MVP strategy you are currently castigating yourself for, you learned loads. You understand the market better and know it’s large enough to be worth making some investment. You may now decide that your next problem is scale. You could choose to implement a new version of your product using a scalable microservices approach. Or you may not yet. There are always good arguments either way and more than one way to scale. Have the discussions and make a reasoned decision. Ultimately, having to move from a monolith to a Cloud Native architecture is not the end of the world as we’ll hear next.
However you arrive at it, a monolithic application is often your actual starting point for a Cloud Native strategy. Why not just throw it out and start again?
It’s hard to successfully re-implement legacy products. They always contain more high-value features than is immediately apparent. The value may be years of workarounds for obscure field issues (been there). Or maybe the hidden value is in undocumented behaviours that are now taken for granted and relied upon by users (been there too).
Underestimated, evolved value increases the cost and pain of replacing older legacy systems, but it is real value and you don’t want to lose it. If you have an evolved, legacy monolith then converting it to microservices is not easy or safe. However, it might be the correct next step.
So what are folk doing? How do they accomplish the move from monolith to microservice?
I recently discussed with Daniel Van Gils of the DevOps-as-a-Service platform Cloud66 what their customers are doing with Cloud Native. The data was very interesting.
Cloud66 hosting is container-based so all of their customers are containerised, but how they are utilising containers and how that has progressed over the past year draws a useful picture.
In June 2016:
In January 2017, they revisited their figures to see how things had progressed. By then:
So, in 2016 96% of those who had chosen to containerise on the Cloud66 platform were not running a full microservice-based Cloud Native architecture. Even 6 months later 90% were still not fully Cloud Native. However, Cloud66’s data gives us some idea of the iterative strategy that some folk with monoliths are following to get to Cloud Native.
The Cloud66 data suggest that, at least for their customers, businesses who choose to go Cloud Native often iteratively break up an existing monolithic architecture into smaller and smaller chunks starting at the front and working backwards, and integrating third party commodity services like DBaaS as they go.
Iterative break-up with regular deployment to live may be a safer way to re-architect a monolith. You’ll inevitably occasionally still accidentally drop important features but at least you’ll find out about that sooner when it’s relatively easier to resolve.
So, we can see that even a monolith can have an evolutionary strategy for benefitting from a microservice-oriented, containerised and orchestrated approach - without the kind of big bang re-write that gives us all nightmares and often critically undervalues what we already have.
So, there are loads of different cloud native approaches:
Many enterprises do several of these things at once in different parts of the organisation and then tie them together - or don’t.
So is only one of these approaches correct? I take the pragmatic view. From what I’ve seen, for software the “proof of the pudding is in the eating”. Software is not moral philosophy. The ultimate value of Cloud Native should not be intrinsic (“it’s fashionable” or “it’s more correct”). It should be extrinsic (“it works for us and our clients”).
If containers, microservices and orchestration might be useful to you then try them out iteratively and in the smallest, safest and highest value order for you. If they help, do more. If they don’t, do something else.
Things will go wrong, try not to beat yourself up about it like a crazy person. Think about what you learned and attempt something different. No one can foresee the future. A handy alternative is to get there sooner.
In this post I’ve talked a lot about strategies for moving from Monolith to Microservice. Surely just starting with microservices is easier? Inevitably the answer is yes and no. It has different challenges. In the next post I’m going to let out my inner pessimist and talk about why distributed systems are so hard. Maybe they obey Conway’s Law but they most definitely obey Murphy’s Law - what can go wrong, will go wrong. But does that matter?
Read more about our work in The Cloud Native Attitude.