This article will explain what microservices are and their costs and benefits. We will show that although the underlying principles are nothing new, they do provide a convention for good software development practices.
Microservices is a word that describes an architectural pattern for software. Initially coming to light in 2011, it is now gaining more traction in the software industry.
It involves a convention for breaking apart larger code bases into smaller code bases that can be independently developed and deployed by defining a boundary for the smaller ones. This boundary stipulates that each smaller code base will cover a lesser amount of responsibilities and provide fewer functions. However, they may talk to each other or to associated business systems to achieve larger business goals. Typically, these smaller code bases would be understood and maintained by a few developers rather than a large team.
In order to gain an understanding of what they are it is easier to understand them in the context of the pattern that they supersede; the "Monolithic SOA" (Service Oriented Architecture). The Monolithic SOA would start by defining a complete set of business objectives (requirements) and would seek to implement this functionality in one application.
For example, a few years ago I worked on a project that handled large amounts of data for various companies around the world that needed to manage their supply chain. This application needed to be able to:
In our monolithic service, all of these suites of functionality are developed and deployed together. In the microservice architecture we would develop and deploy them independently. This diagram explains the difference:
Microservices aren't anything complicated: it just means splitting your application up into smaller applications.
The term 'microservices' is definitely one of those new trendy phrases that gets everyone whipped up every few years, but nothing in the microservices movement is completely new. The basic ideas behind it are underpinned in Object Oriented programming (OO).
Microservices help to promote the above OO topics and are novel because they force developers to derive many of the benefits of well-designed Object Oriented systems by making them physically divide out the individual parts of the overall system. That is really the unique part of microservices, but of course well experienced OO engineers have been doing this for years. The difference then was that the physical separation didn't necessarily exist, only a logical one.
Let's have a look at some key drivers behind why you would want to implement microservices.
A basic tenant of agile is focus. The idea is that focussing improves productivity and reduces errors. Because microservices takes the stance of highly focussed and modular design, it allows teams to focus on one thing at a time. This will have 3 benefits:
Microservices enable better productivity due to specialisation and focus
Keeping software modular like this is nothing new. For years the software community has been talking about something called the Single Responsibility Principle. What this principle says is that when you sit down to write some code you should evaluate the design and ask yourself if the individual components do 'one' thing? If they don't you should try and break it up. Applying single responsibility in practice can be difficult because:
Unless you have really good code review processes or do a lot of pair programming, software can quickly violate this principle and become a web of interconnectedness. A microservices architecture guards against the 'single responsibility' problem because it forces the software developers to disconnect their designs from each other. It can also be useful to systems architects because it allows them more precise control over what components should be doing.
Microservices force better design through the use of convention due to the physical separation of code
Developers are constantly trying to hide complexity. As a system grows beyond a non-trivial size, any well intentioned teams will come up with new designs that attempt to hide internal details of one module from another. Microservices can help because they must expose behaviours through their interface and not low level implementation details.
Better encapsulation of functionality can decrease the number of bugs because modules become simpler to understand and consume.
Microservices help the system as a whole to become more stable by providing clean interfaces for each suite of features to interact
Because of the encapsulation of knowledge in each microservice, developers are better able to hide the technological choices for each selection within the service itself. What this means is that more technologies can be interconnected through common formats. This will have two advantages:
You can protect yourself against legacy issues and ensure better scalability through the distributed nature of microservices
Dealing with legacy systems will be easier for you with a microservice based architecture. This is because smaller code bases are not as badly impacted upon by upgrades. At the same time, scalability will be improved because you only need to scale what you need.
Nothing in application development comes without costs. As you begin to investigate your digital transformation options you need to investigate potential pitfalls. With microservices there are 3 main ones you need to consider.
By separating your system into smaller systems you may end up with more complexity in the way that it works as a whole. Depending on your outlook this may or may not be a good thing. Is it better to be able to understand an entire large system or to have to comprehend a system made of smaller parts?
In the large systems of Monolithic SOA you may reach a critical mass where no one can understand it. But with a smaller systems of microservices (where different teams may maintain each system) you may encounter communication overheads.
It’s worth noting you will now have remote logical dependencies between systems but you will still have to manage these dependencies somehow. Using client libraries and another OO principle inversion of control can help with this. Two posts which detail this are:
Microservices increase overall system complexity because everything is split up
At best, you will be connecting your microservices over a network based protocol such as (TCP/IP) and at worst, over an application based one (such as HTTP). Both of these are much slower than 'in-process' communications than you would experience in a single code base which is packaged and deployed onto a single machine. In a microservice based architecture, network traffic will probably increase because you will need to make more calls between services.
For example, for large transaction platforms such as e-commerce or video streaming, you may need to invoke several services at the same time. For this reason, you need to be confident that your application infrastructure can handle even the slowest of these services.
Microservices can have a bigger impact on network resources
You will experience higher costs to deploy your microservices since you have to store separate code bases, maintain more continuous integration/continuous deployment pipelines and potentially have more environments.
Microservices create a bigger overhead for deployments
In order to obtain robust end-to-end testing you may want to write behavioural integration tests. In the world of the monolith this is much easier since your test can execute all the code in one go. With microservices this is more difficult because of the separation. It is possible to package and deploy multiple services into one testable infrastructure and then re-deploy them into different ones with a high degree of confidence (I will cover how to do this in another article so do sign up to our Newsletter).
End to end testing of microservices is more difficult
If an organisation decides to move to a microservice based architecture it should ideally be done in a gradual way to decrease risk. Instead of re-writing applications from the ground up it may be worth considering a couple of alternatives:
Both recommendations place an emphasis on mitigating risk. Taking a 'total rewrite approach' to developing and building out microservices can be fraught with problems such as lack of documentation, poorly understood code, etc.
The first and foremost step before beginning the gradual transition is to implement robust automated testing. This testing can be applied over current functionality whilst the applications are switched to new architectures gradually.
In this article we have seen how microservices provide a convention of splitting up large code bases up into smaller more discreet modules. In itself this is nothing new and has it’s roots embedded in the Single Responsibility principle of OO.
We then looked at the costs and benefits which can be summarised with the following slide :
If organisations decide to move to a microservices based architecture they should attempt to slowly improve their legacy/monolithic applications and add automated testing. Once this is done, then they can slowly begin to slowly refactor out smaller parts of the code and include this within their new microservice architecture.