Blogs

Published At Last Updated At
akash.png
Akash MoreSoftware Engineerauthor linkedin

Comprehensive Guide to Microservices Design Patterns

Microservices architecture is a popular approach for designing software applications as a collection of loosely coupled, independently deployable services. Here's a comprehensive guide to the key design patterns in microservices architecture, updated for 2024.

microservices banner image

1. Saga Pattren

The Saga pattern is a design pattern used to manage distributed transactions in microservices architectures. Instead of using a global transaction to ensure data consistency across multiple services, the Saga pattern sequences a series of local transactions where each local transaction updates a service and publishes an event. The following local transaction is triggered by the previous event. If a local transaction fails, a compensating transaction is executed to undo the changes made by the previous transactions.

saga pattren

Key Concepts

1. Choreography vs. Orchestration :

Choreography: Each service produces and listens to events and decides if an action should be taken. There is no central coordinator.

Orchestration: A central controller (orchestrator) tells each participant what local transaction to execute.

2. Local Transactions :

Each step in the Saga is a local transaction, which is a sequence of operations within a single service.

3. Compensation :

If a local transaction fails, the Saga pattern must compensate by undoing the changes made by the preceding transactions.

Steps in a Saga Pattern

  • Order Service :

Create an order and publish an "Order Created" event.

  • Payment Service :

Upon receiving the "Order Created" event, process the payment and publish a "Payment Processed" event.

  • Inventory Service :

Upon receiving the "Payment Processed" event, reserve the items and publish an "Inventory Reserved" event.

4 .Shipping Service :

Upon receiving the "Inventory Reserved" event, ship the items and publish a "Order Shipped" event.

2. Database per Service Pattren

The Database per Service pattern is a microservices architectural pattern where each microservice has its own dedicated database. This pattern is essential for achieving the decoupling and independence that microservices promise. Each service can choose the database that best fits its requirements, and services can evolve independently without impacting others.

Key Concepts

1. Isolation :

Each microservice manages its own database schema. There is no shared database among multiple services.

2. Polygolt Persistence:

Different services can use different types of databases (e.g., SQL, NoSQL) based on their specific needs.

3. Encapsulation:

The database schema is private to the service. Other services interact with the data through the service's API.

Advantages

1. Loose Coupling :

Services are decoupled from each other at the database level. Changes in the database schema of one service do not impact others.

2. Scalability :

Each service can scale independently. Services can use the database technology that best meets their scalability requirements.

3. Resilience :

Failures in one service’s database do not directly affect other services.

4. Flexibility :

Different services can use different database technologies tailored to their needs, enabling polyglot persistence.

Implementation Strategies

1. Database Per Service :

Each service has its own database and directly manages its data. There is no shared access to the database between services.

2. API Communication:

Services interact with each other through APIs. If a service needs data owned by another service, it makes an API call to the owning service.

3. Event-Driven Communication :

Services communicate through events. When a service changes data, it publishes an event. Other services subscribe to these events and update their own databases accordingly.

The Database per Service pattern is essential for achieving the autonomy and scalability goals of a microservices architecture. It provides numerous advantages, such as loose coupling, scalability, and resilience, but also introduces challenges, particularly around data consistency and management. By combining this pattern with other strategies like event-driven communication and the Saga pattern, you can effectively manage the complexities of distributed data in a microservices ecosystem.

3. API gateway pattren

The API gateway pattern is a design pattern often used in microservices architecture to manage and route client requests to the appropriate backend services. It acts as a single entry point for all client interactions, providing various functionalities such as request routing, composition, transformation, authentication, rate limiting, and monitoring. Here's a detailed breakdown of the API gateway pattern:

Key Features of the API Gateway Pattern

1. Request Rouitng :

The API gateway routes incoming requests to the appropriate backend service based on the request URL, HTTP method, headers, etc.

2. Request Composition :

The API gateway can aggregate responses from multiple backend services into a single response for the client. This is particularly useful when a single client request requires data from multiple services.

3. Request Transformation :

The API gateway can modify requests and responses, translating between different protocols or formats as needed. For example, it can transform a REST API call into a gRPC call.

4. Authentication and Authorization :

The API gateway can handle authentication and authorization, ensuring that requests are properly authenticated before reaching the backend services. This centralizes security logic and reduces redundancy.

5. Rate Limiting and Throttling :

The API gateway can enforce rate limits to prevent abuse and ensure fair usage of the backend services. Throttling helps in protecting services from being overwhelmed by too many requests.

Implementation

1. Deploy the API gateway :

Use a dedicated API gateway service (e.g., AWS API Gateway, Kong, NGINX, Apigee) or implement your own using frameworks like Express.js or Spring Cloud Gateway.

2. Define Routing Rules :

Configure routing rules that map incoming requests to the appropriate backend services.

3. Implement Middleware :

Add middleware for handling cross-cutting concerns such as authentication, logging, and rate limiting.

4. Set up Monitoring and Logging :

Integrate with monitoring and logging tools to track API usage and performance.

The API gateway pattern is a powerful tool in microservices architecture, providing a centralized entry point for managing and routing client requests while handling various cross-cutting concerns. Despite its added complexity, the benefits it offers in terms of security, performance, and maintainability make it a valuable component in modern distributed systems.

4. Aggregator design pattern

The aggregator design pattern is used in software architecture to combine results from multiple services or sources and present a unified response to the client. This pattern is commonly applied in microservices and distributed systems to simplify client interactions by aggregating data from different services into a single response.

aggregator

Aggregation Pattern has 03 different branches (03 ways that you can implement aggregator pattern):

1. Parallel aggregation (Scatter gather pattren):

In Parallel aggregation, requests are sent to necessary services parallelly. Then the responses are aggregated and the response is sent back to the consumer.

The use case for Parallel aggregation :

  1. When attendance service invoked parallel calls are sent to personal information and leave information. Get responses, aggregate them and sent them to the attendance service.
  2. When the attendance service is invoked, you can send parallel calls to personal info. service and leave info. service. Then get responses from both services and aggregate them as a single response to the attendance mgt. system(consumer).

2. Chain Pattern (Service Chaining) :

Unlike parallel aggregation in the chain, pattern requests are not sent to services parallelly.

Use case Chain pattern:

  1. Using chain pattern when a service has a dependency on another service.
  2. The leave system is still in a previous version where it's not aware of fetching data with employee id (empId) in DB. Instead, it sends employee code (empCode) to fetch data.
  3. So, what you can do as a solution is, you can invoke personal info. service and get employee code (empCode) from that. Then pass the employee code (empCode) into leave info service (with along other information) and get leave information. And now you can send the aggregated response back to the consumer.
  4.  It's not necessary to get something from the first service, but one after the other.

Time Consumption in parallel and chain pattern:
  1. Assume that, personal info. service consumes10ms and leave info. service consumes 10ms.
  2. If we use parallel aggregation, you can get both information (theoretically only, practically not possible) in 10ms and may deliver the response in around 15ms to the consumer.
  3. If we use the service chaining approach (one after other) what happens is 1st call will take 10ms, 2nd call will take 10ms and altogether it will take 20ms and it could take around 25ms to deliver the response

3. Branch Aggregation :

    Based on a factor, a decision is made about where the service should go next. Branch aggregation can be used to call different chains, or a single chain, based on the requirement.

    Use Case for Branch Aggregation :
  1. There is a service where users send user id (userId) and branch code (branchCode). This request goes to the personal info service.
  2. Then, If the branch code (branchCode) is “sales”, the request next goes to sales info. service or if the branch code (branchCode) is “engineer”, the request should go to technology info. service.
  3. The major advantage of using Aggregator Pattern is flexibility for requirements.

5. Circuit breaker design pattern

In the world of distributed systems and microservices, ensuring system stability and resilience is crucial. The Circuit Breaker design pattern is a powerful tool to prevent cascading failures and maintain the overall health of your system. In this blog post, we'll explore the Circuit Breaker pattern, understand its working, benefits, and how to implement it effectively.

The Circuit Breaker design pattern is a resilience pattern used in software development to prevent cascading failures and enhance the stability and reliability of systems, particularly in distributed systems and microservices architectures. It acts as a safety mechanism that temporarily stops the flow of requests to a failing service to allow it time to recover. Here’s an overview of how it works and when to use it:

circuit breaker

Key concepts

States of the Circuit Breaker

1.Closed state:

  1. Requests flow normally to the service.
  2. Failures are tracked.
  3. If the failure count exceeds a threshold, the circuit transitions to the Open state.

2.Open State :
  1. Requests are immediately rejected or redirected to a fallback mechanism.
  2. The service gets time to recover.
  3. After a defined timeout, the circuit transitions to the Half-Open state.

3.Half-Open State:
  1. A limited number of test requests are allowed to pass through.
  2. If the requests succeed, the circuit transitions back to the Closed state.
  3. If the requests fail, the circuit returns to the Open state.

When to use the Service Breaker Pattern

  • Handling Service Failures : Prevent cascading failures when a service is down.
  • Managing Timeouts : Avoid repeated timeouts affecting system performance.
  • Improve Stability : Isolate failures to maintain overall system health.
  • Advanced Features :

  • Exponential Backoff : Implement a recovery timeout that increases with each successive failure.
  • Monitoring and Logging : Track state transitions and failure reasons for better diagnostics.
  • Dynamic Adjustments: Adjust thresholds and timeouts based on real-time performance metrics.

The Circuit Breaker design pattern is an essential tool for building resilient and stable systems. By understanding its states, implementation, and benefits, you can effectively use this pattern to manage failures and improve the reliability of your services.

6. Asynchronous messaging

Asynchronous messaging is a communication method where messages are sent between services without requiring the sender to wait for a response from the receiver. This pattern decouples the services, allowing them to operate independently and handle tasks concurrently. It is particularly useful in microservices architectures to improve scalability, resilience, and flexibility.

messaging

Key Concepts of Asynchronous Messaging

1.Message Broker :
  • Description : A middleware component that facilitates the exchange of messages between services.
  • Examples : RabbitMQ, Apache Kafka, Amazon SQS, NATS.
  • Functions : Stores, routes, and delivers messages, ensures message durability, and supports different communication patterns like publish-subscribe and point-to-point.

2.Message Queue :
  • Description : A sequence of messages held in a buffer until they are processed by the receiving service.
  • Benefits : Ensures messages are processed in the order they are received, allows for load leveling by smoothing out spikes in workload.

3.Topics :
  • Description : A channel where messages are published by producers and consumed by multiple subscribers.
  • Benefits : Supports broadcast communication, allows multiple services to react to the same event.

4.Producers and Consumers :
  • Producers : Supports broadcast communication, allows multiple services to react to the same event.
  • Consumers : Services that receive and process messages from a message broker.

5.Eventual Consistency :
  • Description : A consistency model where updates to a system are propagated eventually, ensuring all parts of the system are consistent over time.
  • Benefits : Improves performance and availability by not requiring immediate consistency.

Asynchronous Messaging Patterns

1.Publish-Subscribe Pattern :
  • Description : Producers (publishers) send messages to a topic, and multiple consumers (subscribers) receive those messages.
  • Use Cases : Event notifications, logging, real-time updates.

2.Message Queue Pattern :
  • Description : Producers send messages to a queue, and consumers pull messages from the queue to process them.
  • Use cases : Task distribution, load balancing, order processing.

3.Event Sourcing :
  • Description : Events represent state changes and are stored in an append-only log. Services react to these events to build their current state.
  • Use Cases : Auditing, reconstructing past states, building read models.

4.Command Query Responsibility Segregation (CQRS)
  • Description : Separates the read and write operations into different models. Commands update the state, and queries retrieve the state.
  • Use Cases : Complex domains, scalability, performance optimization.

Benefits of Asynchronous Messaging

1.Decoupling :

Services can operate independently without being tightly coupled, improving maintainability and scalability.

2.Scalability :

Asynchronous communication allows for horizontal scaling by adding more consumers to handle increased load.

3.Resilience :

Systems can handle partial failures more gracefully as services can retry message processing without blocking the entire workflow. 4.Flexibility:

New services can be added to consume messages without impacting existing services, facilitating easier system evolution.

Get in touch with us now
Hire expert microservice developers and consultants
Microservices

Conclusion

The adoption of microservices design patterns represents a significant shift in software architecture that offers numerous advantages in terms of scalability, flexibility, and maintainability. By decomposing monolithic applications into smaller, loosely coupled services, organizations can achieve greater agility and responsiveness to changing business requirements. This architectural style supports continuous delivery and deployment, enabling faster innovation and time-to-market.