eCommerce Application
8 min read

Microservices Architecture and the most important design Patterns

By unni@sayonetech.com Feb. 24, 2022, 2:19 p.m. Application development company
Share This Article
Modern commerce - It's evolution from the monolith to microservices

The challenges posed by the market led to the development of modern MACH principles-based solutions.


Download Ebook

Microservices architecture fully makes use of the ‘divide and conquer’ rule for its efficient operation. Granular and lightweight, multiple small services work in synergy to perform all functions of an application.


Table of Contents

Subscribe to
Our Blog

We're committed to your privacy. SayOne uses the information you provide to us to contact you about our relevant content, products, and services. check out our privacy policy.

Microservices Architecture and the most important design Patterns

Microservices are becoming more popular by the day. According to a survey by Statista, in 2021, approximately 37 percent of respondents said that their organizations were making partial use of microservices. Large corporations have adopted microservices and become market leaders in innovation. For the newbies, microservices are all about splitting large software systems into smaller subsystems which are essential processes that can be independently deployed. Each of these services communicates via APIs.

 

inner image

 

A key aspect to understand is when to use microservices architecture. Microservices works best when:

  • You are attempting web-scale applications development
  • When you are starting enterprise-level applications development and multiple teams work on the development
  • When you are looking at long-term gains compared to short-term gains
  • Your team has software architects /senior engineers capable of designing microservices systems

Design Patterns for Microservices Architecture

Software design patterns are reusable portions of the code that can be used in software design. Design patterns make use of a common vocabulary and also use tested solutions instead of reinventing the wheel. Using the right design patterns help to implement best practices when setting up microservices architecture. 

Database per microservice

Whenever a large monolithic system is replaced with smaller microservices, one of the most important decisions is regarding the databases. In a monolithic software application, a central database is used. Some software architects prefer keeping the database as it is, even in a microservices architecture. This works almost like an anti-pattern in large-scale systems as the microservices will remain tightly coupled (because of the database layer). The objectives of moving to microservices, such as team empowerment and independent development will not be realized.

A better approach would be to provide one database to every microservice and this makes for loose coupling between the services. The term database may be misleading as the separate database only means logical separation of data, i.e., the services may share the same physical database but would be using separate collection/schema/table. 

Read our Blog “Microservices Architecture – When and How to Shift”.

Event Sourcing

In a microservices architecture, when the design has a database per microservice, the services have to exchange data. For the system to be fault-tolerant, resilient, and highly scalable, they communicate asynchronously by exchanging events. In this case, to have atomic level operations, you will have to update the database and then send the message. For SQL databases if you want to have distributed transactions (for high data volumes), two-phase locking (2PL) is not used because it does not scale. In the case of NoSQL databases for a distributed transaction, you may not be able to use 2PL (many of them do not support 2PL).

Here, event-based architecture with event sourcing can be used. Here, state-changing events are stored instead of entities. Any modification of a business entity is stored as a series of immutable events. The current state of a business entity is thus deducted by reprocessing all the events of that entity at any given time. 

Command Query Responsibility Segregation (CQRS)

It is challenging to read from the event store in case event sourcing is used. To fetch a business entity from any data store, all the entity events have to be processed. There also may be different throughput and consistency requirements for reading/write operations.

In these types of use cases, it is best to use the CQRS pattern wherein the data modification (Command) part and data read part (Query) are separated. CQRS pattern’s two forms are ‘simple’ and ‘advanced’. Whereas in the simple form ORM models are used for reading and writing, in the advanced form, the read/write operations use different data stores. 

Saga

If you set up microservices with a database per microservice design, then managing consistency by using distributed transactions turns out to be challenging. You cannot use the 2PL as it either does not scale as in the case of SQL Databases or is not supported by NoSQL databases.

In this case, you can best use the Saga pattern (for distributed transactions) which is an old pattern developed in 1987 as an alternative for long-running database transactions (in SQL databases). A modern version works well for distributed transactions as well. In the Saga pattern, a local transaction sequence in which each transaction updates the data in the database within a single microservice publishes an event or generates a message. The first transaction here is initiated by an Event or Action. When a local transaction is complete, the message/event that is published triggers the next one.

Backends for Frontends (BFF)

Most modern business applications with microservices architecture have the frontend application separated from the backend applications and are decoupled. They communicate via APIs. For a mobile app client, you cannot use the same backend service as that for the web client. The API requirements are different for the two clients because of different screen sizes, performances, displays, energy sources, and network bandwidth.

The BFF pattern is used in scenarios where each UI gets a separate customized backend. This also has other advantages, such as acting as a facade for some of the downstream microservices, thereby reducing chatty communications between the said UI and the microservices. Also, in some cases, the BFFs provide higher security.

Download and read our ebook “Porting from Monoliths to Microservices - Is the shift worth it”.

Are you looking to outsource microservices development? Call us today!

API Gateway

In microservices architecture, the UI generally connects with many microservices. In such a case, this condition gives rise to chatty communications. Many other concerns such as SSL termination, authorization, authentication, logging, throttling, etc., can arise in the case of large enterprises.

One way to overcome these issues is to use an API Gateway. API Gateway is located between the client application and the backend microservices application acting as a facade. It works like a reverse proxy, routing client requests to the appropriate backend service. It enables the client requests to fan out to multiple microservices and returns the aggregated responses to the client. 

Strangler

Migrating from legacy monolithic applications to microservices architecture is quite challenging as it may the availability of the application. A solution here is to make use of the strangler pattern which allows incremental migration from the monolithic application to microservices architecture. The process allows the gradual replacement of specific functionalities with new microservices. These functionalities are only added in the microservices section, bypassing the monolithic application. 

An API Gateway is then configured to send requests between the monolith and the new microservices. After complete migration to microservices, the facade is designed to intercept the client request and route it to the new service. After all, the monolith's functionalities are migrated, the existing monolithic application is decommissioned or ‘strangled’.

Circuit Breaker

During synchronous communication in microservices architecture, one service usually calls others to fulfil specific business requirements. Such a call can fail due to transient faults such as timeouts, slow network connection, or temporary unavailability. Retrying calls can be used to fix the issue. However, when the problem is severe, the microservices may be down for a longer period. Retrying does not bring in results and precious resources may be lost in these conditions. Also, failures may cascade throughout the application. Failing immediately may not cause as much harm as this one.

Choosing the circuit breaker pattern is a solution for such use cases. One microservice should request another microservice via a proxy working like an electrical circuit breaker. The proxy works based on a count reflecting the number of previous recent failures. It then decides whether to proceed to allow the operation or return an instantaneous exception.

Externalized Configurations

Every software application will have many configuration parameters for the different infrastructure entities such as the network, database, connected service addresses, certificate path, credentials, etc. Moreover, in an enterprise environment, the application is usually deployed in different runtimes (Dev, Local, Prod). This can be achieved via internal configuration, which is a known bad practice and can give dangerous results such as severe security risk if production credentials may be compromised. 

With any change in configuration parameters, the application has to be rebuilt. This is a critical situation in a microservices architecture environment which may typically have hundreds of services.

It is, therefore, better to externalize all configurations. Here, the build process and runtime environment are separate. This helps to minimize the security risk because the production configuration file is used only during runtime or through the environment variables.

Consumer-Driven Contract Testing

In the microservices architecture environment, many services are often developed simultaneously by different teams. These services work together to run a single business functionality and communicate with one another either synchronously or asynchronously. Integration testing of such microservices is not easy. TestDouble is usually used for faster and cheaper test runs. However, TestDouble does not often represent the real Provider Microservice. 

Also, in case the Provider Microservice changes its message or API, then TestDouble does not acknowledge the condition. Another option that can be used is end-to-end testing. This type of testing is mandatory before production. However, this is a slow, brittle and expensive mode of testing and does not equal integration testing.

Consumer-driven contract testing is something that can help in this situation. Here, the owner of a consumer microservice team writes a test suite containing a request and the expected response or expected messages (for synchronous and asynchronous communication, respectively) for a specific provider microservice. These are called explicit contracts. For provider microservice, all the contract test suites (of its consumers) are added to the automated test. When this test is performed for a specific provider microservice, the tests are run and the contract is verified. Here, the contract test maintains the integrity of communications in an automated fashion.

Conclusion

It is vital for any development team that wants to successfully adopt microservices architecture to follow a set of best practices. This in turn requires the selection of the best design patterns for a smooth and successful transition.

How SayOne can Help

At SayOne, we offer independent and stable services that have separate development aspects as well as maintenance advantages. We build microservices especially suited for individuals' businesses in different industry verticals. In the longer term, this would allow your organization/business to enjoy a sizeable increase in both growth and efficiency. We create microservices as APIs with security and the application built-in. We provide SDKs that allow for the automatic creation of microservices.

Our comprehensive services in microservices development for start-ups, SMBs, and enterprises start with extensive microservices feasibility analysis to provide our clients with the best services. We use powerful frameworks for our custom-built microservices for different organizations. Our APIs are designed to enable fast iteration, easy deployment, and significantly less time to market. In short, our microservices are dexterous and resilient and deliver the security and reliability required for the different functions.

Start your microservices journey! Give us a call today!

 

 



 

Share This Article

Subscribe to
Our Blog

We're committed to your privacy. SayOne uses the information you provide to us to contact you about our relevant content, products, and services. check out our privacy policy.

Need top engineers for your team?
Got a project on your mind?

We collaborate with visionary leaders on projects that focus on quality and require the expertise of a highly-skilled and experienced team.

Get in touch