The industry continues moving towards Microservices architecture, meaning a big shift in the organization of companies. Here we tackle the main concerns that you should address to prosper when implementing Microservices.
The concept of Microservices architecture spun around nine years ago, but the adoption curve still faces several challenges before becoming the majority in the industry. This is mainly due to the fact that this architecture is a lot more dependent on the organization’s models, practices, and processes to achieve success.
Microservices aren’t only a technological change, they are a big shift in how to organize your entire company. Let’s dig a bit deeper on the main concerns that any IT department will need to carefully address in order to succeed when implementing Microservices.
The minimum independently deployable piece of code
First of all, let’s briefly define what we mean by a Microservice. Taking concepts from Domain Driven Design, one may think of a one-to-one relationship between a bounded context and a development team, with no dependencies to other context/teams (or as few as possible). If you’re working in a big organization, it’s easy to realize that following this definition will generate work with tens and even hundreds of Microservices — a complex, distributed network of processes interacting with each other.
Although you can start off with a very simple Microservice, the more of them you build, the more you realize about the common code and interdependencies among them. With a few dozen Microservices, the complexity increases, the abstraction layers start to pile up, and the learning curve for new teams to start building more Microservices becomes steeper.
If every team works as independently as possible, in its own bounded context, many of them may end up building similar, duplicated code (as there will be a lot of common code, building blocks that form part of many of the Microservices under development). The communication among the teams and the creation of a common codebase that serve as a foundation for the rest of teams’ Microservices, as well as a set of common guidelines, become key to tackle the complexity.
Organizational structure
Microservices solve an organizational problem. They don’t solve a technical problem. You’ll need incorporate that organizational shift before you even go down the Microservices approach. That’s what stops late adopters and is the reason why there are so many people out there still running highly complex monoliths in very traditional organizations.
When you realize your organization is taking too long to build and deploy new business features, the technological change isn’t the key (although it is an important aspect). The organization itself, its structure and processes, will really make the difference.
This architecture can be seen as a node of independently deployed artifacts that interact with each other to fulfill a business requirement. Governance is decentralized, and each Microservice can manage its own SDLC.
Now, how does this compare to the departments and organizational charts within your IT department? Historically, enterprise organizations tend to form a hierarchical structure around the functionality that is provided by several departments. Information and decision flows from up to down with some minor exchanges across the departments.
The difference between the company’s structure and the business capabilities that will serve as the basis for Microservices architecture need to be carefully addressed and understood by all members of the organization. Here we cite Conwey’s law (1967):
“Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.”
Organizational maturity to deal with these different representations of the systems is a precondition (a must) to succeed. Being autonomous as a team and being able to take ownership of every independently deployed unit is the only way to guarantee that Microservices can evolve. Having Microservices independently deployed implies that you don’t need to ask the Payments team if you can deploy your Billing Accounts Microservice (which makes calls to the Payments domain), because you no longer have those dependencies.
It is also important to understand that your company doesn’t necessarily need to rely on Microservices architecture to speed up your development or to build successful software systems. For some contexts, Microservices may be of great help, but you have several other options that may work just fine, so don’t force your company to adopt a technology the organization isn’t prepared to adopt.
Distributed asynchronous communication
One of the most common pitfalls when migrating to this architecture is to think that you can create a domain model for your business logic in a similar way to when you work in a monolith non-distributed system. If your original monolith had a good enough object model of your business logic, then just break it into different deployable units, introduce RPC (although in the form of an API REST) instead of local in-process calls and voila, Microservices. This is far from reality — Microservices imply a complex, highly distributed system, and therefore, every remote function adds a failure point that needs to be handled correctly.
When working with Microservices, it’s crucial to break synchronous communication. Synchronous calls just won’t scale when you have hundreds of internal API calls. In order to do so, patterns like event-driven communication (publisher/subscriber) and CQRS (link a CQRS) become the backbone of the entire Microservices architecture.
Event-driven architecture allows a clear separation of flows among the Microservices, thereby allowing the domains to interact with each other with loose coupling. Microservices become consumers and producers of events, avoiding blocking with every user request.
CQRS complements the event-driven nature by splitting Microservices functionalities in between those that need to get read-only access to data (queries) and those that need to modify the data (commands).
These implementation patterns are powerful, but they need to be carefully analyzed. Depending on your business needs, you may end up introducing unnecessary additional levels of complexity. Microservices architectures require a lot of expertise and craftsmanship, so there is no recipe to success by just applying any of these patterns.
Monolith vs Microservices
Whenever someone wants to push towards Microservices, the first argument in favor of the architectural change tends to be related to stopping working with an unmaintainable monolith code base.
But the monolith may not be your problem. People often think that if you need to scale, you have to use Microservices only, which is just not the case. You can absolutely scale monoliths as well. In fact, if you don’t know how to scale a monolith, you’re not going to know how to scale Microservices.
If you aren’t able to scale and maintain a monolith, you will probably have greater problems trying to cope with a Microservices architecture. Here we cite Grady Brooch and Fred Brooks, respectively:
“Adding manpower to a late software project makes it later.”
“Adding Microservices to a bad software architecture makes it worse.”
To sum up
As the industry continues moving towards Microservices architecture, the tooling and infrastructure for such an architecture grows. More and more tools allow you to build a Microservice from scratch with a few lines of code.
However, it doesn’t mean things are easier — less code and greater infrastructure imply increased complexity as the system grows to hundreds of Microservices. You need a mature organizational structure and experienced people that can communicate efficiently and guide the development.
Comments? Contact us for more information. We’ll quickly get back to you with the information you need.