Start course

In this course, we will learn the concepts of microservice and Spring framework.  

Learning Objectives

In this course, you will gain an understanding of the following concepts, with regards to microservices:

  • Performance
  • Failure
  • Integrity
  • Service Version Management
  • Common Code for Microservices

Intended Audience

  • Beginner Java developers
  • Java developers interested in learning how to Build and Deploy RESTful Web Services
  • Java Developers who want to develop web applications using the Spring framework
  • Java Developers who want to develop web applications with microservices
  • Java Developers who wish to develop Spring Boot Microservices with Spring Cloud


  • Basic Java knowledge

Integrity. In a monolith system, it is easy to manage transactions because the application generally has a common database, and all transactions are carried out through that database. Microservices architecture provides us with powerful enhancements. But managing transactions can be tricky through this paradigm because it promotes automizing services in data distribution, so managing data consistency in a distributed system is more difficult. There are three main patterns for transaction management in a microservices architecture. They are basically database per service pattern, two-phase commit, and saga. Database per service pattern. This pattern is appropriate only when a transaction covers a single services data change. For example, you have a microservices architecture like this. If you make a transaction using only person service, then this pattern is adequate. But in the real world, things are not so simple generally. Transactions span multiple services generally.

This type of transaction is called distributed transactions. For example, we have a restaurant automation application. When a customer orders a meal, the transaction spans these three services: create order, update inventory, and customer ticket. Of course you can call these services sequentially and complete the transaction, but there are some issues with such a straightforward approach. First, you might not ensure the ACID compliance. As you know, ACID is an abbreviation of the initials of the atomic, consistent, isolated, and durable. The atomicity ensures that all or none of the steps of a transaction should complete. Consistency takes data from one valid state to another valid state. Isolation refers to the ability to concurrently process multiple transactions in a way that one does not affect another. Durability ensures that committed transactions remain committed irrespective of any type of system failure.

So, let's say in our transaction, if the first two services succeed and the last fails, the data will have been changed in the first two services but not in the last service. It will break the atomicity rule and cause incorrect data. There is another challenge when doing a transaction spanning multiple services. It's about managing the transaction isolation level. It specifies which data is visible for sessions in a multi-session platform. Let's go back to our example. If session A starts the transaction and does the operations of order service successfully, in that time, if session B reads from order service, and session C reads from customer ticket service, the data that they see will be inconsistent, because the changes will have been made in order service and won't have been made in inventory and customer ticket services. The solution for this case can be two-phase commit or two-piece in short. As the name indicates, it consists of two phases. The two-phase commit protocol is a widely used pattern to carry out distributed transactions. In a two-phase commit protocol, there is a coordinator component to control the transaction and the logic to manage the transaction.

The other components are the participating services that run their local transactions. There is a schema representing a basic flow diagram of two-piece. In the first phase, the coordinator asks the services whether they are ready to commit the transaction. The participants return yes or no. This phase is called the prepare phase. If all the participating services return yes in Phase 1, the coordinator asks all of them to commit. If at least one node returns negative, the coordinator asks all services to roll back their local transactions. Everything appears to be in order. However, keep in mind that the coordinator node bears the burden of the transaction and may become the single point of failure. Moreover, all other services need to wait until the slowest service finishes its confirmation. So, the overall performance of the transaction is bound by the slowest service. And also the two-phase commit protocol is not supported in NoSQL databases.

Therefore, in a microservice architecture, where one or more services use NoSQL databases, we can't apply two-phase commit. As you see, there are some issues with the two-phases commit paradigm. So, what is the solution?  In such cases, the saga architecture pattern can be used. It provides transaction management using a sequence of local transactions. A local transaction is the unit of work performed by a service. Every operation that is part of a saga can be rolled back by a compensating transaction. Further, the saga pattern guarantees that either all operation's completed successfully, or the corresponding compensation transactions are executed to undo the work previously completed. This diagram shows us a very basic saga pattern. There's normal flow of transactions and a compensating flow in case of failure. If a failure occurs, then compensating transactions are run from the step in which the failure occurred to the start. It is a basic scheme and to show the functionality of compensating transactions.

Actually, there is a component named saga execution coordinator that is used to implement a saga flow. It contains a saga log that captures the sequence of events of a distributed transaction. In the event of any failure, the saga execution coordinator, or briefly SEC, inspects the saga log to identify the impacted components and the sequence in which the compensating transaction should run. There is a basic schema that represents the transaction flow and behavior of the saga execution coordinator. Each service provides the state of the transaction that concerns them. If an error occurs in any service in any step, then the coordinator runs compensating transactions that are due until that time. So, let's take a short break here my friends, and I'll see you in the next lesson.


About the Author
Learning Paths

OAK Academy is made up of tech experts who have been in the sector for years and years and are deeply rooted in the tech world. They specialize in critical areas like cybersecurity, coding, IT, game development, app monetization, and mobile development.