Microservices : From Principles to Patterns
Tags: microservices, architecture, design, refactoring
Published: 2022-08-18 10:58:00

**Microservice Architecture** is a variant of the _Service Oriented Architecture_ structural style, which decompose an application into a collection of loosely-coupled services, interacting with each other using communication mechanisms like API. 
Microservices aims to provide Scalability, Decentralization, Availability, Isolation from Failures, Real-time Load Balancing etc.

**IDEALS Principles** incorporates key **Principles of Microservice-based Architecture**. It includes some of the SOLID principles. IDEALS stand for _<u>Interface Segregation : Deployability : Event-Driven : Availability Over Consistency : Loose-Coupling : Single Responsibility</u>_
Adhering to these principles poses implementation challenges which are solved with the help of different design patterns.
**Design Patterns** are reusable solutions to commonly occurring problems within a given context in software design. Context here is microservices architecture. These patterns complement each other catering to different layers and problems in an application's architecture, as illustrated in image below :

![Azure Architecture Design Patterns](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4aqr7hwfcnyg1kvpcyse.png)

_Image Details can be referred at : [docs.microsoft.com/microservices-design-patterns](https://docs.microsoft.com/en-us/azure/architecture/microservices/design/patterns)_

Once we decide to Refactor our application from Monolithic to Microservices, first question in our minds is : _"So, what's the plan, how we gonna do it ?"_, as we have an existing function business application in Prod along with multiple new requirements lined up.
One way to do so is via **Strangler Fig Pattern**. Strangler Fig, also called Strangler is named after any of numerous species of tropical figs (genus Ficus, family Moraceae) named for their pattern of growth upon host trees, which often results in the host's death. 
Strangler Fig supports <u>_incremental refactoring_</u> of a legacy application into a new (strangler) microservice application, by gradually replacing specific pieces of functionality with new services via <u>_steady and frequent releases_</u>. 
It consists of two types of services. One, those which implement functionality that previously resided in the monolith, which shrink over time. Second, services that implement new features. 

Another pattern for refactoring is **Anti-Corruption Layer** which implements a _<u>façade between new and legacy applications</u>_, to ensure that the design of a new application is not limited by dependencies on legacy systems.

## I
**Interface Segregation Principle** suggests each microservice interface to attend to a specific need of a client's program. In other words, clients should not be forced to depend on an interface they don't use.
One way to implement the principle is through an API gateway. 
**API Gateway** address the problem of <u>_how an individual service is accessed_</u> in Microservices-based application by helping understand various communication protocols, translate them as needed, modify the request and response to suit the service and the client programs, etc. API gateway <u>_acts as the single entry point for all clients_</u> and handles requests by proxying or routing to the appropriate service or by fanning out to multiple services.

## D
**Deployability Principle** acknowledges critical design decisions and technology choices developers need to make regarding packaging, deploying and running microservices.
Deployability involves:
- Configuring the runtime infrastructure including containers, pods, clusters, persistence, security and networking
- Scaling microservices in and out or runtime environment migration
- Expediting the commit+build+test+deploy process
- Minimizing downtime
- Synchronizing version changes
- Monitoring microservices health to identify and remedy faults

Each service is deployed as a set of service instances for throughput and availability.
The Single Service per Host and Multiple Services per Host patterns are two different deployment strategies, addressing ways to package and deploy them.

**Single Service per Host** deploys each single service instance on its own host. 
This pattern provides <u>_service instance isolation_</u> avoiding resource conflicts and making monitoring and management straightforward, but stands comparatively less efficient to Multiple Services per Host in resource utilization.
**Multiple Services per Host** run <u>_multiple instances of different services on a shared host_</u>. This could be done by deploying each service instance as a JVM process or by deploying multiple service instances in the same JVM.
There are further refinements to this Single Service per Host pattern like **Service Instance per VM Pattern** and **Service Instance per Container Pattern**. 
**Serverless deployment Pattern** is an alternative solution to those mentioned above.

## E
**Event Driven Principle**
One of the critical design decisions to make microservices fault-tolerant is to avoid cascading failures caused by downtimes of dependent services. 
Event-driven Principle helps in this aspect as the producer and consumers of the event are not tightly coupled. The messaging channel used for communication keeps both ends of it independent and hence keeps them loosely coupled. This principle improves reliability, scalability and throughput of the entire system.

**Event Sourcing** is a design pattern implementing this principle, which helps <u>_reliably, atomically update the database and send messages/events_</u>. For example, a service that participates in a saga (explained below) needs to atomically update the database and sends messages/events. Similarly, a service that publishes a domain event must atomically update an aggregate and publish an event, which can be done implementing Event Sourcing. 

## A
**Availability over Consistency**
The CAP theorem essentially gives two options: Availability OR Consistency, along with partition tolerance. 
For microservices, the main strategy that enables the availability choice is <u>_data replication_</u>, which can be achieved via **Service Data Replication pattern**, **Command Query Responsibility Segregation (CQRS)** pattern etc. CQRS separates the design and implementation of operations that change data (commands) from the ones that only read data (queries).
Message replication through **Event Sourcing** Pattern (event-driven architecture) generally works on <u>_Eventual Consistency_</u>, keeping Availability over Consistency.

## L
**Loose Coupling** is a coupling technique used to _<u>describe the degree and intent of interconnected but non-dependent components</u>_ within an information system. Loosely coupled with other services - enables a team to work independently the majority of time on their service(s) without being impacted by changes to other services and without affecting other services.

Several strategies can be used and combined to promote afferent (incoming) and efferent (outgoing) loose coupling. **Afferent coupling** is a measure of how many other services use a specific service as Incoming and **Efferent coupling** is a measure of how many different services used by the specific service as Outgoing.
Single responsibility is the idea that enables modeling microservices that are not too large or too slim because they contain the right amount of <u>_cohesive functionality_</u>.

Few Design Patterns promoting loose coupling are Database per Microservice, Saga, API Gateway, BFF, Saga etc.

**Backends for Frontends (BFF)** creates separate backend services for different types of clients, such as desktop and mobile. That way, a single backend service doesn't need to handle the conflicting requirements of various client types. This pattern can help <u>_keep each microservice simple, by separating client-specific concerns_</u>.

**Database per Microservice** suggests each microservice’s persistent data private to that service and accessible only via its API. A service’s transactions only involve its database. 
Here, tight coupling is being handled at database layer. 
Separate data store doesn't imply only a database for each service, rather <u>_Private-tables-per-service_</u>, <u>_Schema-per-service_</u> or <u>_Database-server-per-service_</u>, as per requirement.
When we implement Database per Microservice, some business transactions span multiple services, hence need to implement transactions that span services arises, which is addressed yet another patter known as **Saga Pattern**. 
Saga is <u>_a long lived transaction that can be broken up into transactions, but still executed as a unit, ensuring eventual consistency_</u>.
Few other database related patters are **API Composition** and **Command Query Responsibility Segregation (CQRS)** pattern which provide ways to <u>_implement queries_</u>.

## S
 **Single Responsibility Principle (SRP)** is about having cohesive functionality in an OO class. The notion of single responsibility can be extended to the <u>_cohesiveness of services within a microservice_</u>. The microservice architecture style dictates that the deployment unit should contain only one service or just a few cohesive services. If a microservice is packed with responsibilities, that is, too many not quite cohesive services, then it might bear the pains of a monolith.

Here, we have seen only a bunch of design patterns with only few microservices principles. It is wider topic which cater to variety of domains, use-cases and challenges.

<u>References :</u> 

[microservices.io](https://microservices.io/)
[martinfowler.com](https://martinfowler.com/)
[docs.microsoft.com](https://docs.microsoft.com/en-us/azure/architecture/)
[wikipedia.org](https://en.wikipedia.org/wiki/Microservices)
[cs.cornell.edu](https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf)
[lokajittikayatray.com](https://www.lokajittikayatray.com/post/the-ideals-principles-every-microservice-developer-should-know)
[infoq.com](https://www.infoq.com/articles/microservices-design-ideals/)
[wikipedia.org](https://en.wikipedia.org/wiki/Interface_segregation_principle)
[britannica.com](https://www.britannica.com/plant/strangler-fig-tree)
[techopedia.com](https://www.techopedia.com/definition/639/loose-coupling)
[stackoverflow.com](https://stackoverflow.com/a/15289401)

<u>Image References :</u>
[docs.microsoft.com](https://docs.microsoft.com/en-us/azure/architecture/microservices/images/microservices-patterns.png)