Microservices are trendy and they’ve become the default architecture for hundreds of companies around the world. Companies like Amazon, Netflix and Uber use microservices. Does that mean that they are good for your project? Don't risk falling into a cargo cult mentality, just assuming that “If microservices are good for Netflix, they’re good for us!
I've always tried to cut through the hype and help companies to decide if microservices are right for them.
Many companies aim to solve the problems that microservices cause, some of them plan to do the migration to microservices but don't know how to start.
Business today is more complex, distributed over the continents, performed 24/7 over the internet, and deals with different currencies and time zones. Applications need to meet business needs which are getting more complex. They are supposed to process huge amounts of data, be mobile, use geo-localization, and communicate with external systems. What to do if you are starting a new project or having an issue?
Starting a new project or planning a migration from monolith to microservices
How do you take an existing system and re-architect it without having to stop all other work? How do you break apart existing systems into a microservice architecture? - Those are everyday questions for companies who plan migration to microservices.
My clients face challenges when starting with microservices, and clients with existing architectures (non-microservice-oriented) struggle with adapting microservice architecture, thus I decided to create a series of blogs that will hopefully help answer those questions.
Before we dive into working with microservices we need to make sure that we're speaking the same language. It's important that we have a common, shared understanding of what microservices are.
What is a monolith?
When all functionalities in a system are deployed together (one unit of deployment), we consider it a monolith. It's a single integrated application most of the time written all in one programming language. There are many types of monolithic systems, the most popular and commonly used are the single-process, modular, and the distributed monolith.
The Single Process Monolith
The most common example of monoliths is a system where all of the code is deployed as a single process. All code is packed into a single process and all processes read or store data from a database.
Figure 1. A single-process monolith: all code is packaged into a single process.
These single-process monoliths represent the vast majority of the monolithic system that I can see people are struggling with.
The Modular Monolith
The single process consists of separate modules, each module can be worked on independently but still need to be combined for deployment as shown in Figure 2. The concept of breaking down software into modules is well known in the history of building software applications.
Figure 2. A modular monolith: the code inside the process is broken down into modules
If module boundaries are well defined, it can allow for a high degree of parallel working. For many companies, the modular monolith can be a good choice. Shopify is a great example that has used this approach as an alternative to microservice decomposition. One of the challenges of this technique is that the database tends to lack the decomposition we find at the code level. I have seen some teams having the database decomposed along the same lines as the modules, as shown in Figure 3. This can be very challenging even if you are leaving code alone. We will explore those patterns in further blogs.
Image 3: A modular monolith with a decomposed database
The Distributed Monolith
“A distributed system is one in which the failure of a computer you didn’t even know existed can render your own computer unusable.”
A distributed monolith is a system that consists of multiple services but the entire system has to be deployed together. In our experience distributed monoliths have all the disadvantages of a distributed system and disadvantages of a single-process monolith.
Challenges of Monoliths
There are many challenges that monoliths bring, some of them are listed below:
Size & Complexity
Adding features over the time increases the size and complexity of a single application. So every time when you add a new feature a codebase becomes bigger and more complex. (Size complexity)
Effort of next change
Effort to add a new feature to the monolith goes up as it gets bigger. The bigger the monolith gets, the harder it is to change.
As you have more people working in the same place, they get in each other's way. Every developer expects to add features across the entire application code base. Different developers want to change the same piece of code, different teams want to push functionality live at different times. Who owns what and who makes decisions.
Release Cycles and Quality
It may take weeks or months to deliver a new revision. Delivering one feature requires regression testing of all applications.
What Advantages Can Monoliths Bring?
The single-process monolith has a whole host of advantages.
Simpler deployment topology
It can avoid many of the pitfalls associated with distributed systems. You simply need to deploy the final artifact on the appropriate runtime, configure a few properties and that's all.
Code reuse can be simplify
If we want to reuse code within a distributed system we need to decide whether we want to copy code or push the shared functionality into service. Many people like this simplicity, all code is there and just use it!
Simple to scale
You just run multiple instances of the same application behind a load balancer and you are done. Note that scaling can be more expensive, a monolith requires scaling every part because it's all connected.
Simpler end-to-end testing
Most of your tests test a single piece of software.
What Are Microservices?
Microservices architecture is about building a single application and spreading accumulated features into a network of different services. Each microservice runs their own process developed and deployed independently. Microservices are a set of practices meant to increase the speed and efficiency of developing software solutions that scale. This set of practices is technology agnostic, meaning that there is not one single technology or programming language to build microservices. You can build microservices in all programming languages.
Microservice is made of „Micro“ and „Services“.
How big should a microservice be? How to measure the size? Is that number of lines of code, the number of developers in the team, etc.? There is no universal measure.
The Micro refers to the scope of the service functionality. A microservice is a service built around a specific business capability that can be independently deployed. We call that bounded context. To build a large enterprise application we have to identify subdomains of our main business domain and build each sub-domain as a microservice.
Independently deployable component of bounded code that interoperability through message-based communication. The original definition they gave summarizes it all:
“The microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms”
What Advantages Can Microservices Bring?
There are many advantages of microservices.
The independent deployment
The independent deployment is the most important part. It opens up new models for the scale and robustness of systems.
There is not one single technology or programming language to build microservices. You can build microservices in all programming languages. Process isolation makes it possible to mix different programming languages, programming styles, deployment or databases. Mix of different technologies and work in parallel is allowed.
Scale the number of developers
It can also be easier for developers to understand their part of the system, as they can focus their attention on just one part of it. Process isolation makes it possible.
We are able to implement a more robust architecture because the functionality is decomposed — that is, an impact on one area of functionality need not bring down the whole system.
What Problems DO they create?
Goal of microservices is to spread accumulated features into a network of different services. Goal of services is to use multiple machines. Every communication between machines is a network call and is not instantaneous. That means we have to worry about latencies. Latencies will vary, which can make system behavior unpredictable. We should take into consideration that networks sometimes fail or packets get lost etc. Monolith has simple activities with transactions, while with microservices it's much more difficult. How to get a consistent view of data across multiple machines.
We got familiar with microservices and the difference between microservices and monolith architecture. We covered major and most used types of monolith architecture. As we have seen, monolith architecture has some advantages as well as challenges, the same as microservices architecture.
Considering that each architecture has some advances and challenges, which architecture to choose for the next project? Now that we have a common, shared understanding of what microservices are, in the next blog article I will discuss when microservices are a bad idea and why to choose microservices for your project. Stay tuned.