In a world where a competitive edge is everything, digital transformation is a top priority for modern corporations. The result is a major dilemma for companies. Do they buy new applications even if they don’t meet all their needs? Or, do they develop for innovation and a perfect fit with existing systems to protect their past investments?
No matter what the decision, there is a need for custom development and integration. The result is an extensive portfolio of applications and integrations with other vendors and technology that supports the business—a portfolio that too many times needs considerable maintenance. So, the focus moves from delivering products to dealing with all these applications coherently.
It's this time-consuming effort that created the ideal conditions for a decoupled service strategy. This strategy can follow an SOA architecture, which typically uses a complicated enterprise service bus (ESB) to provide centralized inter-system communication. Or, the company adopts microservice principles, where lightweight and ubiquitous communication is used.
Independent of the decoupled approach you choose, what’s the right path? Should we pick up a sledgehammer and break the monolith into pieces or not?
Are Microservices for Everyone?
A lot has been said about microservices, the well-established star in the walk of architecture fame. However, is it for everyone? Are we all to follow the examples of Netflix, Amazon, eBay alike—these companies with huge products?
One can undoubtedly understand the benefits of self-contained services that are available via a communication protocol over a network. Multiple teams can have independent continuous delivery/continuous integration (CD/CI) pipelines while capitalizing on different skills, vendors, and technology. However, it is essential to understand when it pays off. After all, not all companies require that many teams or that complex of a team setup.
Let's take a look at what you get with different approaches, and maybe we can understand that sometimes a good solution doesn’t necessarily mean a good choice.
So What Are the Tradeoffs?
In a monolithic approach, all application components are tightly connected using the same technology, which dramatically simplifies the implementation of business transactions that require the chaining of multiple services. The tradeoff is clearly on the generated dependencies that become more difficult to deal with in more complex systems. This not only makes a CD/CI strategy almost impossible, but it also makes it painful to scale the solution due to code complexity and long deployment times.
In a decoupled architecture that follows microservices principles, application features are composed by calling self-contained services. These can be implemented by different teams at their own pace, scale independently, thereby reducing the complexity of the solution. They are mostly independent of vendors, products, and technology, using a communication protocol over a network. However, the decoupled service architecture comes with a significant invoice for data transaction consistency and resilience in the fact of communication hiccups.
The fact of the matter is that both approaches have their highs and lows. Because, yes, a monolithic architecture is not a good approach in the long run, but it can jump-start app development in a way that microservices cannot. So, maybe the solution is somewhere in the middle—an approach that takes advantage of both by maximizing the merits and minimizing the weaknesses.
Creating a Third Way
Making good decisions about your architecture is key to the success of your apps, and this is only achieved with a complete understanding of the benefits and costs of the available approaches. It’s in these moments that the concept of Domain-Driven Design (DDD) introduces interesting criteria to guide your decisions.
DDD drives the development of complex systems based in decoupled domains of technology artifacts.
What does this mean? You can define domains that are oriented by the line of business or by CD/CI pipeline, thereby providing a highly independent ecosystem that your teams can manage at their own pace and needs.
For a domain-driven approach to succeed, it’s critical that you clearly define what a domain is in the context of your company so that you can apply the two most important rules of this approach:
- Strong coupling within the domain. All the services within a domain that are exclusive to it can and should be strongly coupled. Your transactions will be faster and can scale without jeopardizing the health of the architecture.
- Loose coupling across domains. Use an API for independent resource consumption across domains.
Another important aspect of this approach is the definition of domain. You have two types. Vertical domains support applications for a LOB or product family. Horizontal domains typically support your foundation services. These are the services that are reused across the vertical domains.
The nature of their loose connections allows for vertical domains to provide a limited amount of services without compromising independence.
Domaining the World
By defining your domains correctly and following these two rules, you get the best of two worlds. You will have an architecture that is highly reusable but at the same time highly efficient.
Are you thinking, “So, what’s the catch?” Here’s my simple answer. Defining domains and setting independent teams is not always easy for some companies. Many times, the lines of business are not clearly delineated; at other times, your architecture is so strongly coupled that the investment to decouple it is huge. In this case, some decision-makers may be afraid to take this step. There are lots of potential barriers.
But at the same time, you can attain these benefits if you are willing to tackle the barriers and fight the resistance to change. This is the true challenge of any digital transformation!