Best way to handle partial failures when calling several external APIs in one request? #196086
-
🏷️ Discussion TypeQuestion 💬 Feature/Topic AreaCode Search and Navigation BodyOur endpoint needs to call three external services (payment, inventory, notification). If the payment succeeds but inventory fails, we end up with an inconsistent state – the user is charged but the order is not confirmed Rolling back the payment is complex (refund API is asynchronous). What patterns can we use to keep data consistent without introducing a distributed transaction (like 2PC)? Examples in Go / Java / pseudo‑code appreciated TY :D |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
|
HElp me someone |
Beta Was this translation helpful? Give feedback.
-
|
You’ve described a classic case for the Saga pattern. Instead of a single atomic transaction, you break the operation into small steps, each with a compensating action (a rollback step) Saga approach (example for your case) Pseudo‑code (simplified): type Step struct {
Action func() error
Compensate func()
}
steps := []Step{
{Action: chargeCard, Compensate: refundCard},
{Action: reserveStock, Compensate: releaseStock},
{Action: sendEmail, Compensate: func() {}},
}
func executeSaga(steps []Step) error {
for i, step := range steps {
if err := step.Action(); err != nil {
// rollback previous steps
for j := i-1; j >= 0; j-- {
steps[j].Compensate()
}
return err
}
}
return nil
}Two execution models B) Choreography (event‑driven) Practical recommendations for your case Alternative: transactional outbox without saga Store the intent in your local DB (pending_order) Use a background worker to retry the failed step (inventory reservation) until success After all steps succeed, mark the order as confirmed |
Beta Was this translation helpful? Give feedback.
You’ve described a classic case for the Saga pattern. Instead of a single atomic transaction, you break the operation into small steps, each with a compensating action (a rollback step)
Saga approach (example for your case)
Let’s define the steps:
Process payment → compensating action: refund
Reserve inventory → compensating action: release inventory
Send notification → compensating action: no‑op (or log a failed notification)
You run them in sequence. If step N fails, you run compensating actions for steps 1..(N-1) in reverse order
Pseudo‑code (simplified):