To be or not to be.
To choose Microservices Architecture or not to choose.
It is not a simple question.
This blog post is a good start to explore the concepts, practices, challenges, and benefits of microservices architecture. At the end of this post, you will have a better understanding of microservices to decide why and when to use it.
What is Microservices Architecture Style?
We are living in a
Agile was the answer. Agile Development means to create and respond to the change quickly. By having cross-functional small teams. Each team works on a specific feature. Together, they satisfy the customer’s needs by releasing the product repeatedly in a short amount of time. As a result, they will be quick in achieving the goal.
Microservices Architectural Style represents a good fit!. It means to decompose the software solution into small services and each service should:
- Implement a specific business functionality (feature)
- Independent and running on its own process
- Loosely coupled with the other services
- Communicate with the other services with APIs
- Have a
full automated deployment plan including rollback - Have separated deployment plan so each service can be deployed separately
- a clear way to be monitored regarding errors and performance
- be scaled up or down based on usage separately
- Have separated code base
- Have decentralized governance: no need to use the same technology stack, frameworks or libraries. Technology diversity!
- Have decentralized data scheme design: Persist its own data separately with the suitable data storage type and scheme.
The overall solution will be more flexible for the rapid changes in the near future. The overall business will be:
- able to adopt the quick changes easier
- satisfy the customer’s new needs quickly
- more cost
– effective
But there are always two sides of any story and you have to hear both!
The next section is the challenges you will face when adopting Microservices Architecture.
Microservices Challenges
- It requires a High Skillset in your team
- Complexity
- no code governance
- Data integrity
- potential network latency
- Versioning
- Mature DevOps is needed
Monolithic Architecture
In Monolithic Architecture, the solution consists of one unified big project that
- Implement all business functionalities
- One process runs all services
- relatively tightly coupled services (I know you have them in different classes and different layers but as architecture, they are one unified one code who should all target a specific version of a framework like JVM, .NET or NodeJs)
- one deployment plan
- one code base that all teams are contributing to
- one technology stack
Monolithic architecture shouldn’t be your strategic choice. However, You may need to consider applying it partially in your projects.
After reading this post you will have enough information to compare between them and know how to transform your business to Microservices if you need that.
Microservices The Big Picture
So After defining Microservices let’s dig more deeper to understand the main components of it.
Microservices Identification
This is the first phase where you hit your first challenge. Identifying the services’ boundaries is the biggest challenge. You have to be aware of business requirements and goals. There are many approaches you can use to define your services.
Domain-Driven Design
The founder of Domain Language and author of Domain-Driven Design is Eric Evans. He introduced it in 2004 when he published his first book:
“Domain-Driven Design: Tackling Complexity in the Heart of Software“
Here are the steps you can follow to apply using the domain-driven design approach:
- Analyzing the business domain and understanding the requirements. Having a domain expert will improve the output of this phase which will compose a set of business models.
- Determine the bounded context of each domain model inside the application domain
- Define the entities, aggregates within each bounded context.
Domain
Each bounded context could be mapped to a microservice. This link has a good example
Domain-driven design eases the communication between team members, improves
But domain driven design has some challenges. It builds the solution based on the concepts of the domain boundaries so it is well designed for domain experts. Projects need more focus on UI/UX approach. So there should be a balance with UI/UX that takes care of the end user’s behavior and how will interact with the solution.
My Conclusions About Service Identification
There are many approaches that are used by solutions architects. Some are using a function-driven approach (top-down). Others are using a data-driven approach based on the data structure (bottom-up). Others are ignoring the functionality and data and focus
My secret ingredient is:
- Don’t stick to one approach and use them all.
- Don’t be a perfectionist when you identify your services. You will need to iterate on it for sure.
- Remember that Microservices Architecture Style is all about responding to the business changes so quickly. so I believe it’s an ongoing process to change and maybe merge or separate services.
- Challenge your design and try to deconstruct it. Do testing prototype and you may find some limitations or stoppers.
- Involving your development team is important and that is related to number 4.
- Get some different thoughts from your solutions architects friends (consider me one! send me an email and I am w
i lling to help)
If you have your own secret ingredient, tell your secret in a comment below and let everybody keep it a secret 🙂
Microservices Authentication
OAuth and OpenID Connect are essential protocols when you need to limit access to your services.
In your solution architecture, there will be an Identity Service that secure your API resources.
If you use .NET Core, you can check my blog post for more details:
How To Use ASP.NET Identity And IdentityServer4 In Your Solution
Microservices Communication
Microservices use two ways of communication with each other:
Synchronous way where the sender waits for the response from the receiver like HTTP.- An a
s ynchronous way where the sender doesn’t have to wait for the response.
There is a trade-off between both ways. The sync way looks more straight forward but it
The async way is more advanced and complex and it has the following pros and cons :
Asynchronous Messaging Pros
- Support multiple receivers which means more scalable way
- Reduce coupling between microservices by having a messaging component in between
- When the receiver fails to receive a message, the sender can still send messages to the messaging component that keeps the messages for a configured time
- The internet-facing API which receives end users’ requests will be more responsive because it might just send a message to communicate with another API without waiting for the response.
- The messaging component can be considered as a buffer that stores the messages until the receiver microservice can receive it.
Asynchronous Messaging Cons
- The messaging component is the backbone of this style so it’s not easy to change it later
- Cost of the infrastructure is relatively high
- Adding more complexity to the communication. Handling the messages is not simple: like duplicated message detection, message timeout, messages’ sessions, scheduled messages, handling messages as batches, filtering messages
Messaging Cloud Products
Cloud Provider | Product |
Microsoft Azure | Service Bus |
Amazon Web Services (AWS) | Amazon MQ |
Google Cloud | Cloud Pub/Sub |
Open Source | RabbitMQ |
Data Distributions And Transactions
Every microservice should manage its own data. Data integrity, data consistency, and Queries from different stores, all of that are critical challenges in the
The following are some rules to manage the data:
- You should consider using Eventual Consistency when you need it to guarantee the data integrity between microservices different stores. The core idea behind eventual consistency is how long your solution tolerates to wait until data become consistent cross different microservices.
- For each duplicated data among services, you can consider some service as the source or master of the data. The rest of the services eventually have the same data but you don’t consider it a source of data.
Example: the user profile avatar URL is stored in an accounts service and another copy in chat groups service.
Accounts service is the source of it. when a user updates the avatar URL in the accounts service, chat service will listen to an event (user_avatar_updated) so it can get the new value.
If values are different, I consider the right value is in accounts service and do fix based on that. - Use the Saga pattern for more advanced data consistency cases.
- Use the CQRS pattern when you need to query data from multiple data stores that are under different microservices:
Usually, you can’t optimize the database for reads and writes! you either optimize for reads or writes on a table or collection. CQRS has a good solution for that. T he last point is: when you notice a lot of events between two services regarding data consistency, consider merging them in one microservice. An event-driven design approach could be applied.
Observability In Microservices
Observability practices refer to all measurement, diagnosing and logging activities for microservices. The challenge is how to aggregate the observed data that is collected from many microservices in a way that helps understand the overall behavior of the application and determine the problems if any.
The solution is to use a centralized observability service which aggregates the logs, events,
Cloud Provider | Product |
Microsoft Azure | Azure Monitor Application Insights |
Amazon Web Services (AWS) | Cloud Trail Cloud Watch XRay |
Google Cloud | Stack Driver |
Here are the main things you have to consider as part of observability in your services:
- Health Check API
- Log Aggregation
- Event Tracing
- Exception Tracking
- Application Metrics
Configurations Patterns
Each service in your solution has many different configurations. It’s an
Configurations include database connections, messaging services queues’ keys, blob storage keys, email systems, third parties like payment gateway settings and other settings including sensitive credentials.
The configuration could be stored in local files as part of the service’s artifacts. Using the local files is
- Files’ scope is limited to one service, many configurations could be needed a
cross different microservices. so when you change the value you need to update all services’ settings files - When you change the configuration you need to redeploy the service
- Dev, Stage, and Production, each environment will have its own file. What if you want to deploy the same version to a different production environment for each geographical region. Then you have to have a different file for each environment in each region. The result is 3*3 =9 files. Imagine that for each microservice in your system ! 🙂 Good Luck
External Configurations
Another alternative way to store configurations is to have external storage that can be easily managed and can be read by many services.
Migrations Patterns
Systems are like humans, they are growing and aging! Adding more features or maintaining them becomes a challenging mission over time. Replacing them completely should be gradual.
There should be a migration plan to move to a new system or a new architecture. Many patterns can help with that:
- Strangler Pattern: you may check this post for Martin Fowler about it and Strangler pattern in Azure documentation
- Anti-Corruption Layer pattern: it refers to add a layer between the new system and legacy system to translates communications between them. More info on this link about this pattern
What is the Right Architecture for my Project
If you think that Monolithic is a bad choice in all cases, you are missing a very important point. There is always a trade-off when comparing two engineering styles.
You could redesign the solution later when it has predictable growth. You have to know which architecture will be more suitable for your project based on many factors and here are some of them:
- Project size and budget
- Project deadline
- Project expected growth
- Team skillset
- Team capacity
You may start with monolithic because you still don’t know the exact bounded context of the services (this happens usually in startups in early stages) and later migrate to microservices gradually.
Understanding different architecture styles will help you decide which one suits your solutions more.
Conclusions
- Microservices Architecture Style came out to help your business respond to the quick changes not to over
– engineer your project, you should know when to use it. - You have to be ready when adopting this architecture with your team.
- Automation is a core part of Microservices Architecture.
- There is no perfect architecture and change is inevitable.
Finally, I did my best to explain the big picture.