Dieser Blogartikel ist älter als 5 Jahre – die genannten Inhalte sind eventuell überholt.
For my master’s thesis I conducted interviews with industry experts in the field of microservice migration. As a result a guidance is provided by thoroughly analyzing the given migration scenarios. It turned out be a crucial point to understand why organizations seek for microservices.
Today, requirements for software are changing faster than ever. This demands for a an appropriate architecture that enables agility. However, required flexibility tends to be hampered when regarding today’s landscape of web applications. Unintended dependencies that have been growing over time let the architecture look like a Big Ball of Mud (BBoM)
Such BBoM-monoliths exhibit increased complexity. This decreases productivity, due to coordination efforts among various teams. As a countermeasure, organizations may have introduced agile methods such as Scrum to optimize their software engineering processes. However, required technical autonomy lacks more often.
Agility & Microservices
In agile software development, a desirable architecture is flexible enough to handle fast-pacing requirements. Following the principles of the Agile Manifesto , the best architectures emerge in a functional requirement-driven manner. But architecture also demands for design effort upfront in order to enable the intended flexibility . Nevertheless, rigorous, waterfall-like Big Design Upfront (BDUF) is neglected, due to uncertainties of requirements. BDUF does not fit the agile idea of limiting the amount of coherent work effort, also called the batch size .
The microservice approach limits batch size, because every single microservice covers only a part of the whole application . All those parts cover distinct business capabilities, e.g. showing product details in an e-commerce application. The important point is that the responsibility for a single business capability is moved to a single team which demands for cross-functional alignment and a DevOps culture .
Thus, microservices are a modularization concept that accounts for both, technical aspects and those on an organizational level. The idea is to model an architecture around clearly separated business capabilities that are each implemented as a microservice. By implementing their own architecture decoupled from other parts of a system they allow to build large scale software incrementally with small and independent teams  . Thus, microservices are relevant for organizations that aim for reducing the Time-to-Market (TTM) but cannot handle rapidly changing requirements with their current architecture and organizational structure.
Nevertheless, a migration towards microservices includes many challenges. The following points provide a guidance to dump the BBoM and introduce microservices.
The Six-Factor Microservice Migration
A migration towards microservices can be conducted completely detached from but also in dependency with the monolith (factor 1). The essential decision is whether a microservice of the target architecture contains its own frontend or not (factor 2). Already in this stage interactions between technical and organizational aspects become explicit. When it comes to detaching a first microservice from the monolith, it should be ensured that the underlying new model is not corrupted by old ones (factor 3). Migrating during operation should also be secured by taking risks into account and by implementing appropriate measures (factor 4). This can additionally be supported by automated processes (factor 5). Concerning this matter, arising efforts should be prioritized adequately. The required transparency for this purpose can be established by an agile organizational culture. However, coupling an agile transformation with a microservice migration comes with additional challenges (factor 6).
It is often argued that a complete rewrite of an application is fraught with risk of high degree. But the release of the application has not to be accomplished in a manner of a Big Bang. Instead a gradual approach can be chosen. But often a “microservice-monolith-hybrid“ where monolith and microservices form the application together is unavoidable. Especially if there is pressure of competition and new features must be delivered to customers continuously, that hybrid is the only solution. Then, a migration is a long-lasting process, which can last for more than 2 years.
To shorten the time the application is in a hybrid state, it is recommended to perceive a migration as an opportunity for change. In this context change means implementing new requirements, but also accepting omission of existing functionality. On the one hand, it is advisable to reduce migration efforts by considering if the migrated application should be an exact copy of the old one. On the other hand, delivering new functionality, which was not applicable in the old technology stack, strengthens trust from stakeholders. The migration could then be perceived as progress instead of stagnation .
2. System Decomposition
There are two fundamental decisions which must be taken into account. First, there is the decision whether a microservice will be extracted by using the existing code base or by rewriting the functionality entirely. Second, the target architecture must be defined and the decision must be made, whether a microservice comes with its own frontend or multiple microservices are integrated within a UI-monolith.
When using the existing code base a duplicate of that code base is the springboard. Then the given part should already exhibit a high amount of autonomy. Also, this approach has potential success when the extent of the project is limited to fewer persons developing the application. When the challenge is to decouple multiple teams, it is recommended to define that microservices deliver their own frontend.
This requires further discussion of how to interpret microservices in terms of layers. When regarding a three-tier architecture, two types of microservices can be distinguished. On the one hand there are microservices that only contain the data and the application tier (figure 1). On the other hand there are microservices which reach from the data tier up to the presentation tier.
When using those “2-tier microservices“, a UI-monolith is established, when building the frontend out of multiple microservices of this kind. This comes with the risk of coupling teams which integrate their microservices into the same frontend. In contrast, “full-stack microservices“ that deliver their own portion of the frontend, e.g. as UI-fragments, promise a higher degree of autonomy for teams (figure 2).
3. Model Boundary Protection
As a starting point, it is recommended to begin with a single context with moderate complexity. In doing so, it is important to protect the underlying model of the upcoming microservice that implements that context. Therefore, a rule should be postulated that prohibits accessing data from the monolith either through data layer access such as JDBC or immediate API-calls. Instead, data should be transferred asynchronously from the monolith to the microservice in the background while also translating between old and new models. This can be seen as synchronization of two data stores and conforms to the idea of building an Anti Corruption Layer (ACL), a concept of Domain-Driven Design (DDD) . In this context an ACL serves as a model integrity protector of both the microservice and the monolith (figure 3). They allow to establish clean models within the new context ab initio because translation is taken care of within that distinct component .
4. Surveillance of risk
Any migration comes with risks. Especially when doing a complete rewrite, it should be measured with business relevant metrics (e.g. turnover) if the new application leads to equivalent results compared to the existing one. Then, through a gradual delivery of the new application to an increasing number of customers, the economic risk can be controlled. Deployment strategies such as Canary Releasing should be considered at this point. Also it is recommended to test a microservice in the production environment before it is actually rolled out to customers. This can be accomplished by feeding requests to microservices and solely observing their behavior Shadow Traffic. Performance issues can be unfolded without having effect on the application because the respective response is omitted. This practice was depicted by two experts and in literature .
Other measures can also support the reduction of risk during micrsoervice migration. It is useful to be able to switch between old and new implementations using mechanisms such as Feature Toggles. They provide the flexibility to take control of this by only changing configuration and without the necessity of redeploying the whole application.
5. Automation & Tests
To reduce the TTM it is advisable to model and automate the value stream as a deployment pipeline for each upcoming microservice. Here, every step from committing code to deploying a build is considered. This ensures that deployments can proceed often. Additionally, this supports a high degree of test coverage from the beginning, because tests are also part of that pipeline.
When considering test automation, experts reference the so called automated test pyramid. A test pyramid consists of three test layers: unit, service and UI tests. The amount of tests per layer decreases, resulting in a pyramid shape with numerous unit tests and few UI tests. To ensure that multiple microservices integrate with each other as expected, it seems to be reasonable to rely on UI tests. But UI tests are brittle and expensive to develop and maintain . This is why tests in isolation without UI are of significant importance in these cases: it should be possible to test a microservice autonomously using mock objects. With mock objects it is possible to simulate the interaction with other microservices or the monolith. Corresponding tests can be referred to as service-level tests within an automated test pyramid.
6. Agile Transformation
Introducing agile methodologies and migrating to microservices at once is a change of large extent. Hence, it is recommended to split this up into several steps and seek for gradual change over time. Otherwise the risk of reduced motivation and disorientation is too high. By introducing agile methods such as Scrum first, microservices ideally emerge by the strive for autonomy of teams over time.
Although Scrum primarily addresses the software development process within one single cross-functional and product-centric team, also larger scale organizations demand for adoption. Scrum does not provide a solution tackling the coordination of multiple agile teams. There are also solid arguments that scaling agile methods should be avoided for larger projects in favour of splitting the product . Nevertheless, different approaches for scaling Scrum and agile methods have emerged over time. E.g. LeSS (Large Scale Scrum), Nexus and SAFe (Scaled Agile Framework) are relevant approaches to scale agile for larger organizations according to their market shares .
When it comes to establishing agile methods in bigger organizational contexts, it is advisable to start with one team and then add more and more teams. Also in LeSS, this is described as time consuming but a safe way to enable feature-centric teams while breaking down functional silos .
Furthermore, it is advisable to record arising non-functional efforts such as the implementation of an ACL within the backlog and to reasonably prioritize them among other requirements. In SAFe, enabler stories are introduced which could represent the implementation of the above mentioned techniques and mechanisms as well as migration efforts in general . Thus, they ensure transparency and unfold potential interdependencies between business and IT. Hence, prioritization should be conducted with both business and technical people in charge following the recommendations of 2 experts.
Nevertheless, no statement can be made regarding which scaling approach for agility is best suited when migrating to microservices. Only assumptions are possible: Nexus is less suitable, because it necessitates the role of an integration team, which takes care of architectural concerns. This comes with the risk of feature teams outsourcing this responsibility to that special team. Again, LeSS appreciates that architecture is a matter of teams, which underlines responsibility for architecture within every team in contrast to Nexus. Last but not least, SAFe defines the role of superordinate architects. Those are preferable to carry a shared architectural vision on the macro-architecture level but should not decide topics of micro-architecture within the agile teams.
Microservices encompass both technical aspects and aspects of the organizational level. This is why introducing microservices involves measures in both contexts. If not holistically considered, the touted benefits are brittle. From a purely technical perspective, microservices can be implemented using waterfall-ish software engineering methodologies. However, to fully enable autonomy of each microservice, they are embedded into an agile culture.
Particularly, organizations with multiple teams can profit from the non-technical aspects of microservices. Decomposing a system from the data layer towards the frontend decouples teams. Therefore team boundaries reflect best in the architecture when they manifest as vertical units if multiple teams develop an application with a single frontend. Those teams are now able to expedite their part of the application autonomously. This is more difficult in monolithic applications and with layered teams. Here, complex dependencies necessitate the coordination of activities across team boundaries. Therefore TTM decreases.
Because an agile team consists of both, developers and non-technical roles, IT and business working hand in hand is supported. Microservices emerge because agile teams strive for autonomy. When teams decide to move towards microservices, the migration itself has often no value in a sense of a new feature that can be delivered to customers. Nevertheless, microservice migration efforts need to be prioritized properly. This requires transparency. Only if transparency is taken and promoted continuously, agility and microservices quicken each other. If not, there is a high risk of not reducing TTM in a long term.
To avoid building tomorrow’s legacy software when introducing microservices, it is even more important to establish the agile mindset and continuously rethink solutions.
- Beck et. al.: Manifesto for Agile Software Development (2001)
- Cervantes et. al.: Designing Software Architecture: A Practical Approach (2016). Addison-Wesley, Boston, 1st Edition
- Rubin: Essential Scrum (2014). mitp, Heidelberg/Hamburg, 1st Edition
- Nadareishvili: Microservice Architecture: Aligning Principles, Practices, and Culture (2016). O’Reilly, Sebastopol, 1st Edition
- Lewis et. al.: Microservices (2014)
- Newman: Building Microservices (2015). O’Reilly, Sebastopol, 1st Edition
- Wolff: Microservices – Grundlagen flexibler Softwarearchitekturen (2016). dpunkt.verlag, Heidelberg, 1st Edition
- Stevenson: An Agile Approach to a Legacy System (2004)
- Evans: Domain-Driven Design: Tackling Complexity in the Heart of Software (2004). Addison-Wesley, Boston, 1st Edition
- Evans: Getting Started With DDD When Surrounded With Legacy (2013)
- Stine: Migrating to Cloud-Native Application Architectures (2015). O’Reilly, Sebastopol, 1st Edition
- Posta: Low-risk Monolith to Microservice Evolution Part I (2017)
- Cohn: Test Automation: Let Service Be Your Middle Man (2014)
- Fowler: Large Agile Projects (2003)
- VersionOne: The 11th Annual State Of Agile Report (2017)
- Komus: BPM-Labor Hochschule Koblenz: Status Quo Agile 2016/2017 (2017)
- Larman et. al.: Large-Scale Scrum: Scrum erfolgreich skalieren mit LeSS (2017). dpunkt.verlag, Heidelberg, 1st Edition
- Leffingwell: SAFe 4.0 Reference Guide: Scaled Agile Framework for Lean Software and Systems Engineering (2016). Addison-Wesley, Boston, 1st Edition
- Stranghöner: SCS-Architecture (2015)
- Stranghöner: SCS-Architecture (2015)