Build the mental model
A single-database transaction gives you ACID guarantees for free: the database's transaction log can atomically commit or roll back every change together, since it's one system with one source of truth. Once data is split across services or shards — an order-service and an inventory-service each with their own database — no single database can coordinate that commit, yet you still need 'either both changes happen or neither does' semantics. Two-phase commit (2PC) extends the transaction idea across systems: a coordinator asks every participant to 'prepare' (lock resources, confirm it CAN commit) and waits for all to agree before telling everyone to actually commit. This gives strong atomicity, but at a real cost — if the coordinator crashes after some participants have prepared but before the final commit message, those participants are stuck holding locks indefinitely, blocking other work. The saga pattern trades that strict atomicity for resilience: instead of one blocking transaction, it's a sequence of independent local transactions, each service committing its own step immediately, with a predefined compensating action (e.g. 'refund the payment') to undo earlier steps if a later one fails. This is why sagas, not 2PC, dominate real-world microservice architectures.
Connect it to a real scenario
When a Tutorial Platform student buys a course bundle, three separate services are involved: the payments-service charges the card, the enrollment-service grants course access, and the notifications-service sends a receipt email — each with its own database, split apart precisely for the independent scaling reasons covered earlier in this course. If payment succeeds but enrollment fails, the student paid for nothing. Using 2PC here would mean payments-service holds a lock on the charge while waiting for enrollment-service and notifications-service to confirm they can proceed — risky if any one of them is slow or down. Instead, the platform uses a saga: charge the card, then grant access, then send the email, with a compensating refund step wired in if enrollment fails after payment succeeded.
Try the working example
TWO-PHASE COMMIT (2PC)
Coordinator Payment-svc Enrollment-svc Notify-svc
|--- PREPARE ------->| | |
|--- PREPARE --------------------->| |
|--- PREPARE ---------------------------------------->|
|<-- YES, can commit-| | |
|<-- YES, can commit-----------------| |
|<-- YES, can commit----------------------------------|
|--- COMMIT --------->| | |
|--- COMMIT -------------------------->| |
|--- COMMIT --------------------------------------->|
RISK: if coordinator dies here ^, all 3 services sit
holding locks forever, waiting for a commit that never comes.
SAGA PATTERN
Step 1: Payment-svc charges card --- SUCCESS
|
v
Step 2: Enrollment-svc grants access --- FAILS!
|
v (trigger compensation)
Compensating step: Payment-svc REFUNDS the charge
Each step commits locally and immediately.
No service ever waits, holding a lock, for another to decide.The diagram contrasts 2PC's synchronous prepare/commit round-trip, which can leave all participants blocked if the coordinator dies mid-protocol, with a saga's sequence of immediately-committed local steps and a compensating rollback when a later step fails.5-minute try-it
Design a saga for a 3-step 'change subscription plan' flow: (1) charge the price difference, (2) update the plan tier, (3) send a confirmation email. Write out the compensating action for each step, in order, that would run if step 2 fails.
One important caution
Assuming a saga gives you the same isolation guarantees as a real ACID transaction — between steps, other requests can observe partially-applied state (e.g. a payment charged but access not yet granted), so code reading that data must be written to tolerate intermediate states, not assume atomicity.
Writing a compensating action that itself can fail without a plan — if the 'refund the payment' step fails, you now have a customer charged with no course access and no refund; compensating actions need their own retry/alerting logic, not just a hopeful single attempt.
Wikipedia — Two-phase commit protocol — System Design