Skip to content
Discussion options

You must be logged in to vote

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):

type Step struct {
    Action func() error
    Compensate func()
}

steps := []Step{
    {Action: chargeCard, Compensate: refundCard}…

Replies: 2 comments 2 replies

Comment options

You must be logged in to vote
0 replies
Comment options

You must be logged in to vote
2 replies
@typelop
Comment options

@kevpoul
Comment options

Answer selected by kevpoul
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Code Search and Navigation Search, navigate, and understand code on GitHub Question Ask and answer questions about GitHub features and usage Welcome 🎉 Used to greet and highlight first-time discussion participants. Welcome to the community! source:ui Discussions created via Community GitHub templates Other Features and Feedback Discussions that fall into "Other" category
3 participants