Your search did not match any results.
We suggest you try the following to help find what you're looking for:
No one has achieved success with microservices just by talking about them. Unfortunately, many organizations spend a lot of time on exactly that, debating how to approach microservices. It is as though there is one perfect approach to designing and working with microservices that needs only be uncovered. In actual fact, there is no such definitive solution; even if there were, it would hold true only until changes in the organization, business objectives, technology frameworks and regulations made adjustments necessary.
It is tempting—just as it was a decade ago with SOA Web Services—to spend a lot of time and energy on identifying microservices. Creating an exhaustive overview of all microservices, defining the exact scope and interface of each, is not feasible and is not a smart investment of time. It would be a lot of work, and that work would never be complete. The definition of microservices is not an end in itself and giving in to this temptation represents a serious risk. Microservices are an instrument for achieving sustained business agility in a changing world of functional and non-functional requirements and evolving technical, political, economic, and legal parameters. Microservices cannot be defined once and for all, and they should not have to be. As architects and developers we are agile and flexible. We embrace change in all aspects of our IT organizations.
Here’s another organizational risk familiar from the SOA era: starting with an exclusive focus on the technology for implementing microservices and on the microservices platform, the underlying platform for eventually running the microservices (that do not even exist yet and for which no requirements are yet known). It is all too easy to spend time on this seemingly useful exercise and, after months of investigation and selection and architecting, to end up with an impractical, oversized and over-engineered platform – and no running microservices. Such discussions slow down the process of microservice adoption, obstruct the view of the essential challenges, and set up an organization for disappointing results (if not outright frustration).
A third category of risk is to just start building microservices without a clear business need for or objective with a microservice architecture or, even worse, without really understanding what a microservices architecture entails from an organizational perspective. The operative keyword being overlooked: DevOps.
This article provides some insights and guidelines that can help propel teams of architects beyond discussions and into action. Perhaps it can also help establish some architecture guidelines, such as the importance of domain design.
When discussing microservices, we must remember what our objectives are. Microservices are not the objective; they are merely the means. Microservices are meant to help us with those objectives and if they do not do so, we neither need nor want them.
Both in Development and in Operations we want to have better control and more insight so we can change functional and non-functional aspects as dictated by business needs. And we have the impression that microservice concepts and considerations will help us get there.
It’s a reasonable enough question to ask, but apparently it’s a tough one to answer. It seems easier to describe what the microservices architecture is intended for than to explicitly define a microservice itself. Perhaps we tend to stay away from a concrete definition because we find we are not so much in agreement with our peers as we thought we were. Let me try to describe the picture I see in my mind when talking about microservices:
A microservice is an independent business component that we can change, release, scale, relocate, make available, replace, charge for, report on and decide about, without dependencies on other microservices (and their associated teams, owners, users, etc.). A microservice has clear business value and implements a specific business capability. A microservice is owned through its entire DevOps/BusOps lifecycle by a single team of no more than 6-8 people. One team could own a few microservices; each service will fall under precisely one team.
The word “microservice” leads many people to assume microservices are much smaller than “regular” services. But, to me, one microservice can easily comprise several of our typical SOA (Web) Services. In my mind:
Note: I find no clear connection between microservices and containers. Of course, containers are a great vehicle for achieving standardized and automated CI/CD, release, scaling and management, and allow us to package application and platform components together into standalone units; as such, they can be a great help for implementing microservices. At the same time, one microservice can easily be implemented using several containers or totally without using containers.
Microservices are designed from business functionality and responsibility (maximize cohesion vs. maximize decoupling), based on business domain decomposition. Microservices translate to technical stuff, such as deployment artifacts and containers and perhaps database schemas or partitions, and even more to organizational aspects, such as ownership, planning and budgeting, coordination and team management.
Microservices can be compared with departments in a company: relatively separate units with a clear responsibility that can be largely "encapsulated" and are interacted with in largely predefined ways that should not be bypassed by outsiders.
The size and number of departments and their scope is not easily defined in a generic manner. Some are small, some large. Some may consist of just a part timer (e.g., our legal department consists of a specialist hired for 6 hours per week) and others can be fairly large (the pool of truck drivers, for example). As the company grows or diversifies, the departments can be split into more specialized units.
At the departmental level or per department, it is decided how activities are performed, who is hired or fired, where activities are performed and when the department is available to perform work. Too many tiny departments can introduce a lot of overhead and very complex process chains, even though they may allow a high degree of specialization and flexibility. Departments that are too large are hard to manage and may adopt different ways of working. Creating two departments out of a single one or combining several departments into one unit is a fairly common practice, although it may not always be a very smooth transition.
Exploration of the bounded contexts that are the breeding ground for microservices takes place in a similar way as the above search for the optimal departmental structure: as part of domain-driven design. Citing Gérald Croës: "Bounded contexts are the Single Responsibility Principle applied to your domain model. Each part of your system has its intelligence, data, and vocabulary. Each part is independent of one another."
When defining microservices, some general guidelines override all other, more subjective considerations:
As Sam Newman states: "When it comes to how small is small enough, I like to think in these terms: the smaller the service, the more you maximize the benefits and downsides of microservice architecture. As you get smaller, the benefits around interdependence increase. But so too does some of the complexity that emerges from having more and more moving parts. As you get better at handling this complexity, you can strive for smaller and smaller services." (Building Microservices, by Sam Newman, O'Reilly Media, Inc., 2016, ISBN: 1491950358)
Two application sections that are currently part of the same microservice (or monolith) are perhaps better off in distinct microservices if they have stark differences in one or more characteristics, to such an extent that it hampers us or cramps our style. Some measures and mechanisms are expensive, so they should not be wasted on application areas that do not require them. Making functionality Highly Available or Ultra Secure or Supremely Well Tested comes at a price. Identifying areas that need special measures and isolating them as separate components (i.e., microservices) to ensure the elevated levels are focused and applied only where needed is one of the considerations.
The motivation for breaking off a chunk from an existing application component should be the fact that the chunk is currently not (in) a separate microservice makes it harder or more expensive to do things we want to do to only one of them, such as make functional changes, improve availability, test for regression, set up monitoring, train developers, or achieve high level of confidentiality. Therefore, we branch off one or more microservices to remove these limitations that we experience. The effort of branching off and the overhead introduced as a result of having two or more microservices instead of a single microservice is justified by the gains from the independence we realize between the microservices. Otherwise, we don’t do it.
Characteristics that drive the decision to extract one or more microservices from an existing component (when various areas within a component hugely differ in them):
There is no perfect microservices design and certainly not one that will remain a perfect fit forever. Organizations are in constant flux, as is the world around them. What was a great fit yesterday in terms of microservices may no longer match the situation of tomorrow. We might as well face that we do not design for posterity and instead embrace the changes and refactor our microservices accordingly.
The Agile way of working and thinking mandates us to embrace change—change with regard to functionality and priorities and also with respect to technology, process and architecture. This mentality needs to be spread throughout the complete organization from the C-Level down to the clerks in the business departments. This critical aspect is not often seen in organizations.
We should be prepared to modify our microservices design when the situation changes, and be happy for the chance to improve instead of chagrined that our design apparently was not good enough. This can happen, for example, when the decision is made to implement a SaaS service, to outsource part of the business activities, to implement specific security considerations regarding certain types of data, or to merge the organization and its IT assets with another company—or simply when the organization is successful and is growing rapidly.
We should be prepared almost at any time to extract newly identified microservices from an existing application component. When the cracks revealing a candidate microservice begin to show and a certain subset of an existing application component or microservice is found to meaningfully differ from the larger context it lives in (e.g., on one or more of the characteristics listed above), we have to split off that subset as a new microservice.
This will happen so regularly that organizations should have no difficulty going through this process. Given that we will start out with one or very few microservices, it is likely that we will have to split off microservices regularly. We can facilitate that process by preparing for it; just as in the figure above, we should define and visualize the boundaries between subdomains so there is awareness in our team about the areas that, though part of a single entity, should be treated as at least a little separate from each other. We should assign names to these subdomains and use those names in user stories, documentation and in the naming conventions for our software artefacts. Interactions within the microservices and across the border between the subdomains should be created in a considered manner: whenever possible, through the public channel (API or, better yet, events) or at least all through a single interface. There should be no direct references or dependencies between data models in the subdomains.
The biggest challenge with splitting microservices is data. It’s easier to split off code than it is to split data, both the data model and the actual data records. Once data is split, the way transactions are supported must also be reconsidered, at least if transactions were supported across the boundary where we now have two microservices. The transaction design perhaps should be changed, or patterns like SAGA and Event Sourcing must be considered.
Note: The reverse operation of merging two microservices into a single component should be much easier. Formerly heavily decoupled components with disjunct ownership, backlogs and budgets are combined into a single unit with permission—but no mandate—to interact more intimately. In reality, merging mature microservices does not happen very often; a merge will be considered only when there is no justification for having two separate microservices and when the short-term effort to merge is less than the long-term overhead of continuing with the existing situation. Unfortunately, the risk and effort are typically not justified since there is no immediately apparent gain from merging. By having and practicing a clear procedure for merging microservices, just as we have for splitting them, we get closer to embracing change and can get a better fit for the microservices with our organization.
Here’s a simple example: a small organization runs a web shop. Its application landscape has been designed based on the functionality required, the SaaS services subscribed to, the structure of the organization and the user groups. The size of the outfit is also a factor: the IT department is currently very small and the scale of the operation is very limited.
However, it is clear from the beginning that the logistics microservice comprises areas of functionality that are related but distinct as well. Warehousing (keeping track of the stock and ensuring that replenishment is done from vendors and) Shipping (picking orders up from the warehouse and transferring them to shipping partners for delivery to customers) are both part of Logistics. They have touchpoints and definitely deal with similar aspects of the business, yet they are different.
It is too early for this organization to break up the Logistics domain into Warehousing and Shipping (and more?), but it makes sense to recognize the separate areas that may well evolve into distinct microservices. We do this by associating user stories, documentation, software artefacts, etc., explicitly with their respective sub-domains when naming and organizing them. Additionally, we try to prevent any direct dependencies between artefacts from these two subdomains. The data models should be kept separate. Interactions between the two subdomains should be explicitly managed, documented and implemented, ideally through external APIs and events.
In the same organization, a similar example is provided by the Orders and Shopping Cart. Right now, they not only share one bounded context but they are also implemented in a single service. However, chances are that Ordering and Shopping Cart will evolve separately and change for different reasons. They may eventually become separate services—and perhaps distinct bounded contexts. We will then have to consider the split in data and define events so the two pieces of functionality can still interoperate. even though now they’re fully decoupled.
The fewer microservices we need to achieve our true objective, the better it is. More microservices means more overhead and costs; in terms of organizational responsibilities and work coordination; complexity and administration effort (cross-domain transactions, more moving parts to oversee, monitor); resource usage (each microservice requires additional infrastructure resources); and performance (highly decoupled interactions across microservices will take considerably longer in terms of network latency than internal calls within a microservice).
If one microservice could bring us all we need, that would be great! One component that does it all: is that therefore a monolith? Well, literally it is. But it should not have the challenges commonly associated with monoliths (such as hard to scale, hard to change), or it would be broken up into multiple microservices.
In reality, in most situations our application landscape will be heterogeneous along various axes and too big to be taken care of by a single team. Because of relevant differences between various areas in our application landscape, we might entertain the thought of splitting off some areas as microservices. Ultimately, it is the functional design—translating to bounded contexts—that probably is the biggest deciding factor in designing the microservices and therefore the eventual granularity.
Note: an interesting discussion can be held around the distinction between bounded context (an area of shared, consistent business terminology and data model language along with all persistent data stores, aligned with a business sub domain) and microservice. We could argue that several microservices (with, e.g., different scalability requirements) can be created within one bounded context. In terms of business responsibility and DevOps ownership, ideally the bounded context is not split up and if there are in fact multiple microservices for pragmatic reasons, they should all be owned by the same team.
Suggestions, contributions and general feedback from the following people have made this a better article, and I thank them for it: Jeroen Kooij, Luis Weir, Sven Bernhardt, Michiel van der Sluis, and Sander Rosenhart.
[1] Building Microservices, by Sam Newman, O'Reilly Media, Inc., 2016, ISBN: 1491950358
http://gorodinski.com/blog/2013/04/29/sub-domains-and-bounded-contexts-in-domain-driven-design-ddd/ [2] “Sub-domains and Bounded Contexts in Domain-Driven Design (DDD)” by Lev Gorodinski , April 2013 - http://gorodinski.com/blog/2013/04/29/sub-domains-and-bounded-contexts-in-domain-driven-design-ddd/
[3] “How big is a microservice?” by Ben Morris, March 2015 - http://www.ben-morris.com/how-big-is-a-microservice/
[4] “Thoughts on the macro architecture and the infrastructure for microservices” by Michael Douglas, April 2018 - https://medium.freecodecamp.org/microservices-from-idea-to-starting-line-ae5317a6ff02
Lucas Jellema is solution architect and CTO at AMIS, based in the Netherlands. He works as a consultant, architect, and instructor in such diverse areas as Database and SQL, Java/Java EE, SOA/BPM and PaaS and SaaS Cloud Solutions. The running theme through most of his activities is the transfer of knowledge and enthusiasm (and live demos). An Oracle ACE Director and Developer Champion, Lucas is a well-known speaker at Oracle Code, Oracle OpenWorld, JavaOne, Devoxx and various User Group conferences around the world. His articles have appeared on Oracle Developer Community, the AMIS Technology weblog and in magazines and websites around the world. Lucas is the author of Oracle SOA Suite 11g Handbook (2010, McGraw Hill) and Oracle SOA Suite 12c Handbook (2015, McGraw Hill)