You probably don't need a Microservices Architecture.
Introduction
We all love new concepts. They incite us to learn, and they tickle our appetite for knowledge. New concepts emerge rapidly, but only a few gain traction. At first, they are often coined to respond to a problem specific to a context, but they tend to be generalised afterwards.
It is safe to say that infrastructure is hard, often times, to get right and maintain correctly; hence the multiple architecture patterns developed. Before talking about Microservices, let's talk about our alternative contenders.
- The monolith: It consists of a single, self-contained, and tightly integrated unit. This unit will handle all the business logic, data access, and user interface interactions. It is generally simpler to develop, test, deploy, and scale. Often times, a monolith will grow and become difficult to maintain.
- The modular monolith: It consists of a single application that is divided into multiple blocs or modules. These modules should be loosely coupled and highly cohesive. So by design, this architecture should offer more flexibility than a monolith.
- The hybrid: It consists of dividing your source base into a mashup of modules, huge blocks, and microservices. Whatever suits your subjective needs.
- The rest: Many other architectural designs are nuances of these designs. The majority are solutions for data-related challenges.
Microservices
It is a design in which an application is split into a collection of services. They are:
- Focused on the business logic
- Loosely coupled and highly cohesive
- Highly maintainable and testable
- Owned by a small team
- Independently deployable
Apart from the fact that all these points can be found in modules, what does a Microservices architecture bring to the table?
- Simplicity: provides simplified development of large scale enterprise level application.
- Scalability: Code can be broken into smaller parts that can be developed, tested, deployed, and updated independently.
- Reliability: It ensures no single point of failure by providing replicated server groups that can continue when something breaks. It restores the running application to good condition after failures occur.
- Focus: The developer focuses on solving business problems and business logic.
- Availability: Back-end data must always be available for a wide range of devices...
- Responsiveness: It enables distributed applications to scale in response to changing transaction loads...
This is a very promising list of pros, but are they really exclusive to Microservices (no, they are not)? How about the cons?
Fallacies of Distributed Systems
Microservices architecture is a distributed system architecture. Fallacies of distributed systems stemmed from a presentation by L Peter Deutsch to his peers at Sun Microsystems, Inc. The presentation was made back in the 1980s, 40 years ago. They still hold true.
- The network is reliable
- Latency is zero
- Bandwidth is infinite
- The network is secure
- Network topology doesn't change
- There is one administrator
- Transport cost is zero
- The network is homogeneous
While designing a Microservices-based application, these fallacies tend to be ignored or downplayed. If not, the focus is shifted only to those problems that we can "solve" using other software and vendors. The problem is often shifted but not mitigated. For example, we can solve the network topology changes by implementing a service discovery tool. What we did, however, was shift the problem by adding a new tool or service to maintain and monitor.
Why Microservices
What we fail to recognise, or at least admit, is that the Microservices design was created out of an organisational need. Historically, teams were often segmented by skillset. The development team will be in charge of developing features; the QA team will test the new features and ensure non-regression; the DBA team will ensure the schemas are up-to-date and that database is ready; and the infrastructure team will operate the application and provision resources for it. You can see straightaway that this type of organisation creates many bottlenecks in the development process. Worse still, if the DBA, QA, and infrastructure teams were serving multiple development teams, everything could come to a standstill. Blockers are everywhere, and a feature's journey from conception to deployment is not smooth sailing.
Now you can see the need to reorganise the teams. Two-Pizza Teams principle was coined by Jeff Bezos. Each team's releases are independent, which means a team has to be a microcosm of an IT team (Dev, QA, DBA, Ops, etc.), and it doesn't mean that one person has one role; rather, one person can, or should I say must, have multiple roles.
Complexity
Microservices should be simple. Well, it depends. Again, if you have a relatively large company with a big IT department and multiple projects, switching to microservices is indeed a solution. But if you have a small to medium-scale project with well-defined requirements, why use microservices? Just modularize your application.
Overhead
Microservices are, after all, distributed systems. Distributed systems have a lot of issues and an enormous overhead. Monitoring, debugging, and network latency—the list is long. Also, depending on what type of data store you are using, the CAP theorem applies. And if you use a distributed data store, data consistency becomes a real issue. Are you going to use CQRS? An Event-Driven Architecture? You are probably trying to solve a problem you don't even have. Build yourself a modular monolith.
Delayed Time To Market
If you are considering starting off a new application using microservices, I think you may be gullible. It is well known that applications change. Business needs mature over time, and you can't predict all that.
To build a microservices-based solution, you need a team of "experts." That will cost you a lot. You will also need a good vision of what the product will be, because when the microservices are defined and their boundaries set, good luck refactoring your code if there is a need to.
What should you do instead?
Understand your needs
Do you have scalability problems? Scaling horizontally or vertically may cost you way less than decomposing your application into independent microservices. Do you really need to decompose your application? Did you try standalone processes or standalone modules in an SOA style?
You want to reduce your development team's dependencies? Reorganise the team and increase communication capabilities across your organisation. A cross-functional matrix management scheme may suffice.
Start simple
Keep It Simple Stupid. Avoid over-engineering at the beginning. The more you overengineer, the more inflexible your system will be (in most cases, at least). The demands will evolve. Keep it simple to keep iterations rapid.
Conclusion
We tend to reuse the same hype points for a lot of products and designs. I always hear the same selling points over and over again. And often times, when you apply the solution, it is far from what has been sold to you. It is human nature to reject that you were fooled.
Each solution has its pros and cons. You have to find what works for YOU. Each context is different, and not all teams have the same exact talent or budget. Adapt accordingly.