Before I start explaining consistency and transactions in microservices, lets have a look at a real world scenario where we might need them.
Lets consider a system which has the following microservices: users, products, payments and orders. If any user purchased a product using this system, it would result in the following steps:
- Quantity is subtracted from the product inventory. (Products microservice)
- Order with a "Pending payment" status is created. (Orders microservice)
- Users active payment method is charged with the order's total amount. (Payments microservice)
- Order is updated with a status of "Payment processed". (Payments and Orders microservice)
Now, if any step fails, that means the product can not be purchased and therefore any changes made before the failing step would need to be reverted back. This would be quite easy in a monolith using transactions but how would we deal with this in microservices?
Don't microservices have transactions?
Simply put, No!
We know that microservices emphasize on decentralizing pretty much everything in order to minimize coupling and advocate high availability. This results in your data spanning over multiple databases and transactions can not occur across databases.
Keeping the CAP theorem in mind, wherever there is Partitioning, we have to choose between Consistency or Availability. Microservices being advocates of high availability, compromise on consistency -- in case you didn't knew, transactions are a way of enforcing strong consistency -- which is why we aim for eventual consistency when working with microservices.
Consistency in microservices
Just because microservices don't have transactions doesn't mean that they can't be consistent. There are a few types of consistencies and (as mentioned earlier) when working with microservices, we aim to achieve eventual consistency. Now, if you're new to developing microservices, you might be wondering that "What is eventual consistency?". Lets go back to our initial example and see how we can solve our problem with eventual consistency.
So, a user purchased some product using the aforementioned system but the payments microservice was down at that time. What should the system do? In favor of being always available, the microservices based system would show the user that the product has been purchased or the payment is still being processed (based on your business logic). In the back-end, whenever the payments microservice comes back up, it'll process all the pending payments and update the related orders automatically. In case, for some reason the payment can not be processed, the system should accordingly change status of the order and notify the user. This would result in the system being consistent eventually.
That is it from me on consistency and transactions in microservices. If you have any confusions or questions, feel free to leave a comment below. Alternatively, you can also reach me via twitter or linkedin.