How will you make sure transactions are completed or rollbacked when two micro services talking to each other ?

Kiran Kumar
4 min readMar 1, 2023

--

When two micro services communicate with each other, ensuring that transactions are completed or rollbacked requires careful design and implementation. Here are some approaches you can take:

  1. Use a distributed transaction coordinator: A distributed transaction coordinator (DTC) is a software component that manages transactions across multiple microservices. When a transaction involves multiple microservices, the DTC coordinates the transaction to ensure that it is either completed or rolled back. Some popular DTCs include Atomikos and Narayana.
  2. Implement compensating transactions: A compensating transaction is a transaction that undoes the effects of a previous transaction. If a transaction involving two microservices fails, a compensating transaction can be used to roll back the transaction. For example, if a payment transaction fails, a compensating transaction can be used to reverse the payment.
  3. Use message queues: Message queues can be used to decouple microservices and ensure that transactions are completed or rolled back. When a microservice sends a message to another microservice, the message is added to a queue. If the transaction involving the second microservice fails, the message can be returned to the queue and retried later.
  4. Implement idempotent operations: An idempotent operation is an operation that produces the same result no matter how many times it is executed. If a transaction involving two microservices fails, an idempotent operation can be used to retry the transaction without causing any harm. For example, if a payment transaction fails, an idempotent operation can be used to retry the transaction without duplicating the payment.
  5. Use circuit breakers: Circuit breakers can be used to prevent cascading failures when a microservice fails. If a transaction involving two microservices fails, a circuit breaker can be used to prevent further requests to the failed microservice until it recovers.

Overall, the key to ensuring that transactions are completed or rollbacked when two microservices communicate with each other is to design your microservices architecture with transaction management in mind. By using tools like distributed transaction coordinators, compensating transactions, message queues, idempotent operations, and circuit breakers, you can ensure that your microservices architecture is robust and reliable.

Ensuring transactional consistency between microservices is a complex problem, but there are a few approaches you can take to ensure that transactions are completed or rolled back when two microservices are communicating with each other:

  1. Use Distributed Transactions: Distributed transactions involve coordinating multiple transactional resources across different systems. You can use a distributed transaction management system like two-phase commit (2PC) or three-phase commit (3PC) to ensure that all the participating services either commit or rollback a transaction together.
  2. Implement Saga Pattern: Saga pattern is a technique for managing transactions across multiple services in a distributed system. Instead of a single, atomic transaction, a saga breaks the transaction down into a sequence of smaller, individual steps. Each step updates the data in a specific service and emits an event that triggers the next step in the saga. If any step fails, the saga can trigger compensating actions to undo any changes made so far.
  3. Use Event-driven Architecture: In an event-driven architecture, each service publishes events to a message broker or event bus. Other services can subscribe to these events and take action in response. By using this pattern, you can ensure that any service that is impacted by a transaction is notified of the transaction and can take appropriate action.
  4. Implement Circuit Breaker Pattern: Circuit Breaker is a pattern that helps to handle the fault tolerance in distributed systems. The circuit breaker monitors the response time of each service and, if a service fails to respond, it can switch to an alternative service or fallback to a default behavior. This helps to ensure that transactions are completed or rolled back even in the presence of partial failures.
  5. Implement Idempotency: Idempotency is a property of a service that ensures that the same request can be executed multiple times without causing unintended side effects. By implementing idempotency, you can retry a failed transaction without worrying about the possibility of duplicating the transaction.
  6. Design Rate Limiter :

The basic idea of rate limiting algorithms is simple. At the high-level, we need a counter to keep track of how many requests are sent from the same user, IP address, etc. If the counter is larger than the limit, the request is disallowed.

Where shall we store counters? Using the database is not a good idea due to slowness of disk access. In-memory cache is chosen because it is fast and supports time-based expiration strategy. For instance, Redis ( show in below picture) is a popular option to implement rate limiting. It is an in-memory store that offers two commands: INCR and EXPIRE.

  • INCR: It increases the stored counter by 1.
  • EXPIRE: It sets a timeout for the counter. If the timeout expires, the counter is automatically deleted.
rate limiter

By using one or more of these techniques, you can ensure that transactions are completed or rolled back when two microservices communicate with each other

More interviews look in this blog ASAP

--

--

Kiran Kumar

Technophile with 10 years experience in IT industry | Java Lead cum Architect