We've previously highlighted the ways microservices architecture can solve the issues of a monolithic architecture. With its ability to scale, adapt, and remain resilient, microservices architecture is the go-to choice for companies looking to take their operations to the next level.
The global microservices architecture market was valued at $2,073 million in 2018 and is projected to reach $8,073 million by 2026, registering a CAGR of 18.6% from 2019 to 2026.
The buzz around microservices is undeniable, but not every software system is cut out for the transition. In this article, we'll explore the unique characteristics of microservices architecture and help you decide if your company is ready to make the jump.
Microservices Characteristics Checklist: Development on the Fast Track
The monolithic code base we had was so massive and broad that no one knew all of it. People had developed their own areas of expertise and custodianship around submodules of the application.
—Phil Calçado, former Director of Engineering, SoundCloud
Imagine being able to develop at the same lightning speed that powers Amazon, Twitter, and Netflix. What do they do differently? All of them gradually moved to the correct microservices architecture at the right time. If you are also at that stage, remember to keep the following characteristics in mind when designing them, namely:
The very definition of microservices starts with small. Dividing a large block into smaller blocks is the fundamental concept of microservices, but determining how small the blocks should be is the big deal here.
Making the wrong cut is the most common error and the first reason for microservices’ failure.
It applies both to the team size and the codebase. Whenever you plan to move on to this design, always be prepared that a block should be small enough that it should not take more than 2 or 3 weeks for your team to rewrite the particular service again.
The right size
Considering the use case of Uber, they also got stuck at "how big should a microservice be?" The important task is to think carefully about the logical role of each domain within the monolith.
For instance, map search was served as one service, and the fare was kept as a separate service. They were successful in bifurcating their single-repo into 80 microservices, each one handling different functionality.
When deciding how big or small a microservice should be, it's important to consider the Single Responsibility Principle, which states that a microservice should have one and only one reason to change. This means that a microservice should be focused on specific functionality, and not try to do too much.
Focused on One Task
Each microservice should be full-stack and intended to carry out a single business function, as this increases focus and efficiency.
Let’s understand this with the Netflix example. Netflix is a streaming service that offers a wide range of features such as video playback, recommendations, and user accounts. To handle this, Netflix has implemented multiple microservices, each focused on a specific task.
Including a separate microservice for handling user accounts that is responsible for managing user information, handling user authentication, and providing access controls. This microservice is focused on one task - user account management.
Allows for more efficient debugging, testing, and deployment as it's easier to identify and fix issues within a specific microservice.
Additionally, enables faster development and release cycles as teams can focus on one task and release their microservice independently.
Aligned with Bounded Context
The bounded context in microservices refers to the specific responsibility or functionality that a microservice is designed to handle. Each microservice is "bounded" by a specific set of responsibilities, and this boundary defines the context in which the microservice operates.
Consider an example of an e-commerce website, that has separate microservices for handling user accounts, product catalogs, and order management. Each microservice is responsible for a specific set of functionality, and they communicate with each other to complete a user's purchase.
For example, when a user adds an item to their cart, the user account microservice communicates with the product catalog microservice to retrieve information about the item and the order management microservice to update the cart. The user can then proceed to checkout, where the order management microservice is responsible for processing the payment and updating the inventory.
In the above example, different microservices are "bounded" by their specific responsibilities and can be developed, deployed, and scaled independently, which allows for greater flexibility and scalability in the overall application.
The ability of each microservice to function independently and make decisions without relying on other microservices makes them autonomous.
Each microservice should have its own:
data store, own data validation, and be able to handle its own business logic.
Each microservice should be able to operate and evolve independently without affecting the functionality of other microservices. Autonomy lets teams choose the best language stack and data model. Each microservice has its own database or persistence layer, that is not shared with other services.
Changes to service A shouldn’t force system B to change or have any other ripple effects. If service A, on which service B depends, goes down, service B should not just blow up.
This allows for faster development and release cycles and enables teams to focus on one task and release their microservice independently. Additionally, it allows for scaling the microservices independently and improves fault tolerance.
Uber Case Study
Autonomous Execution=Independent deployments + clearer lines of ownership
As Uber grew from 10s to 100s of engineers with multiple teams owning pieces of the tech stack, the monolithic architecture tied the fate of teams together and made it difficult to operate independently. As a result, they adopted a microservice architecture. Ultimately, their systems became more flexible, which allowed teams to be more ”autonomous.”
Loose coupling goes hand-in-hand with high cohesion. When loosely coupled, a service knows very little about others. This keeps the service intact. In systems with high cohesion, it becomes possible to keep all the related logic in one service. Otherwise, the services will try to communicate with each other, impacting the overall performance.
Such modules are not only easier to develop and maintain, but they also allow development and testing to run in parallel. Overall, loosely coupled modules reflect higher software design quality.
Being autonomous and loosely coupled, a team can deploy their microservice with little external coordination or integration testing. Microservices should communicate over well-defined APIs and use translation layers to prevent behavior changes in one service from affecting the others.
Independently deployable is much more accurately defined as a service that is packaged as a deployable or executable unit and is production-ready after being tested in isolation.
This service has its own repository for source code.
The deployment pipeline tests the service in isolation through consumer-driven contract testing.
What emerges from the deployment pipeline is a production-ready service that can be deployed.
An essential advantage of a service that may be independently deployed is that it accelerates the deployment process. It reduces the need for laborious, fragile, and time-consuming end-to-end testing of various services. It also eliminates the requirement for teams to coordinate and perhaps impede one another.
As Henry David Thoreau eloquently stated, "What you get by achieving your goals is not as important as what you become by achieving your goals." And when it comes to embracing microservices architecture, the true value lies not only in the end result of deploying user-centric platforms but also in the transformative journey it takes the organization on. A culture of empathy, agility, and progress is the true reward, and it's a goal worth striving for.
What are microservices?
Microservices are a software architecture and design approach that involves breaking down a complex application into a collection of small, independent, and loosely coupled services. Each of these services focuses on a specific business capability or function and operates as a separate unit within the application ecosystem. This architectural style has gained significant popularity due to its ability to enhance scalability, agility, and maintainability in modern software development.
What are the characteristics of microservices?
Microservices are small, independent software components that focus on specific functions. They communicate via APIs, promoting loose coupling and scalability. Each microservice has a single, clear responsibility, making it easier to develop, deploy, and maintain complex applications with agility.