Microservices have gone from being newcomers in the field of architecture to being top dog. But like every other architecture approach, microservices are a trade-off and only solve specific problems.
What is a microservice and what can it do?
There are different points of view regarding the definition of microservices. ISA (independent system architecture) describes microservices as another type of module. In classical systems, features are implemented with programming languages, but microservices are separate processes, or separate virtual machines. Microservices are normally docker containers, a lightweight alternative to virtual machines. Communication happens over the network, for example via REST. This means that microservices are much stronger when they are decoupled than would be possible with modules in a deployment monolith. For example, every microservice can be developed in a different programming language. If one crashes, then the others continue, whereas with a deployment monolith, the entire monolith will crash. If this property is used skillfully, a noticeably more robust system can be developed.
Another important property is separate deployment. A new version of a microservice can be put into production separate from all other microservices. This makes it possible to implement a new feature in a microservice and put it into production without affecting other microservices.
Self-contained systems (SCSs) are a special case of microservices: along with persistence and logic, they contain a web UI. This way, a feature can be implemented in its own SCS, even if the feature includes the UI, logic and persistence. Most technical changes go through all of these steps.
To implement a system, break it down into the following hierarchy:
The diagram shows:
- At the highest level, a system is developed by multiple teams. Scrum recommends teams of five to eight people.
- Each one of these teams should work on an independent work field. Bounded contexts from domain-driven design are useful for this. Each bounded context has its own domain model. In an e-commerce application, it could be a domain model for creating invoices with tax rates, prices and billing addresses. There can then be a separate domain model for delivering orders. Parcel service providers, delivery addresses, sizes and weight would be relevant here.
- Technically speaking, bounded contexts can be implemented in one or more microservices. Technical reasons are important here: If paying an invoice is particularly difficult because it uses an external contractor, then it can be turned into another microservice and be scaled accordingly.
Despite their independence, a lot of decisions must be made on a technical level that affect all microservices. This is macro-architecture, as opposed to micro-architecture, which specifically makes decisions for a microservice. Typical macro-architecture decisions concern microservices’ communication with REST or messaging systems, or standards for the operation of microservices.
This architectural approach has the following advantages:
- Teams can work independently of each other to a large extent. Technical decisions can be made in teams. Teams can use different programming languages or another framework. Of course, it’s also possible to provide standards. Because work fields are decoupled through bounded contexts, professional and technical changes can normally be implemented by one team without having an effect on the other teams. Microservice architecture therefore turns one large project into many smaller ones. That’s also how microservices support scaling of agile processes.
- Because microservices can be deployed individually, it’s a lot easier to implement continuous delivery with them. The state of DevOps report shows that multiple daily deployment not only reduces the time-to-market for new features, but also increases the likelihood that deployments will be executed without problems, enables systems to get back online more quickly after a failure and therefore leaves more time for the development of new features. It is often only possible to deploy multiple times a day when independently deploying small microservices.
- When replacing a legacy system, a part of its functionality can be re-implemented in a microservice. This means that you are not stuck with the technical decisions of the legacy system. The new microservices will use interfaces to the legacy system for integration. This means that the microservices are independent of the internal structure of the legacy system, which is often too complicated. The migration of a legacy system (for example, to achieve faster deployment) is the most common reason for using microservices.
- Microservices promise durable development. In many systems, the architecture is clearly defined at the beginning but more and more dependencies between modules emerge over the course of development and therefore compromise the architecture. This often goes unnoticed. Microservices expose interfaces, for example, with REST. A new dependency in an interface should not just sneak in, it should be programmed out. This decreases the risk of architecture failure. It also means every microservice can be re-written on its own. In a deployment monolith, the entire system would have to be replaced. A re-written microservice can be based on different technology and doesn’t have to keep using the old code. This allows a new beginning. This technological independence also allows a system to be changed to a new technological level more easily: The new version can be individually implemented for each microservice. This decreases the risk and means that some microservices don’t even have to be updated. This makes it a lot easier to deal with technological progress.
In addition to these advantages, microservices also allow simple scalability because only individual microservices have to be scaled. As mentioned, you can be more robust and feel more assured, because communication between microservices and firewalls can be safeguarded, for example. So you don’t necessarily have to be working on a large, complex project for microservices to be useful.
Like all architecture approaches, microservices are a trade-off. An obvious disadvantage is that the large amount of deployable artifacts leads to an increased workload, because all of these artifacts must be monitored. But it’s a plausible market that is taking over many technologies, so that it is always getting easier to operate even larger systems with microservices. This includes dockers and kubernates as container environments.
An architecture that affects many different microservices with any change is problematic: advantages like decoupled development do not apply there. As opposed to deployment monoliths, multiple microservices have to be coordinated in addition to the deployment. That’s why the technical step is so important. Of course, it helps that microservice architecture doesn’t lapse so easily. But it doesn’t seem to make sense to decide against using microservices because you assume that you will notbe able to fine enough technical steps.
Microservices are a good architectural answer to the challenge of agile software development and continuous deployment, but they also have other technical advantages. In the end, they represent another type of modularization and change a fundamental parameter of software development. For more information, check out the microservices book or the free microservices primer or check out my website at: https://ewolff.com/.