Skip to main content
Architecture Patterns

Saga Pattern (Distributed Transactions)

Term 57 of 68 in the ERPStack technical glossary

What is Saga Pattern (Distributed Transactions)?

The Saga Pattern is a microservices design pattern for managing long-running distributed transactions across multiple services without using two-phase commit (2PC), coordinating rollback through compensating transactions.

Saga Pattern (Distributed Transactions) at a glance

Shape
N local transactions, each with 1 compensating action that semantically undoes it
Two styles
2 options: choreography via Apache Kafka events, or orchestration via 1 coordinator
Guarantee
Eventual consistency, not the 4 ACID properties — intermediate states are visible to readers
Requirement
100% of steps idempotent, because retries after a timeout are certain, not hypothetical
Built with
TypeScript 5.9 orchestrators persisting state in PostgreSQL 18 through Drizzle ORM 0.45, steps carried over Apache Kafka, Redis for locks, Sentry and OpenTelemetry Observability on every hop
Numbers that matter
N steps, N compensations; past roughly 4 steps choreography stops being readable; 0 atomic rollback; 1 deadline per step
Compare with
1 ACID Compliance transaction inside a single PostgreSQL Database, available only when 1 service owns all the data, reached over REST or a GraphQL API Schema
Commonly paired with
Apache Kafka transport, Redis locks, Microservices Architecture boundaries, PostgreSQL 18 state through Drizzle ORM 0.45, Docker and Kubernetes workers, Sentry alerting and OpenTelemetry Observability traces
Failure handling
1 deadline per step, 1 idempotency key per participant, 3 outcomes to model — success, compensation, and a stuck saga needing an operator
Coordinator state
Saga state in PostgreSQL 18 through Drizzle ORM 0.45, steps carried on Apache Kafka, Redis holding the per-participant lock, Docker and Kubernetes running the workers.
Where it shows up
logistics, manufacturing and finance flows: 1 order touching an ERP, a CRM and a carrier API, with 0 shared transaction across the 3.

How Saga Pattern (Distributed Transactions) works in production

In a microservices ERP, creating a purchase order might involve updating inventory, creating a billing record, and notifying a supplier API — across three separate services. If the supplier API call fails, the inventory reservation must be reversed. The Saga Pattern coordinates this using either a centralized orchestrator or a choreography of events, ensuring eventual consistency without distributed locking.

The ERPStack approach to Saga Pattern (Distributed Transactions)

We implement Saga orchestration using AWS Step Functions for complex multi-service ERP workflows, defining explicit compensating transactions for each step to guarantee clean rollback on partial failures.

Frequently asked questions about Saga Pattern (Distributed Transactions)

Why is the Saga Pattern needed at all?

Because a database transaction cannot span services. Once payment, inventory and shipping own separate stores, there is no single commit that covers all 3. The Saga Pattern replaces it with a sequence of local commits plus explicit compensations: refund the payment, release the reservation, cancel the label. The rollback becomes a business action you design rather than a guarantee the database provides.

Choreography or orchestration — which should you use?

Choreography keeps services decoupled: each reacts to events and emits its own. It works well for short flows and becomes very hard to follow past roughly 4 steps, because the sequence exists only as emergent behaviour. Orchestration puts the Saga Pattern sequence in 1 coordinator that is readable, testable and easy to reason about, at the cost of a component that knows about everyone. Long flows usually justify the coordinator.

What are compensating transactions in practice?

Business reversals, not database rollbacks. Under the Saga Pattern you cannot un-charge a card by rolling back a transaction that already committed elsewhere — you issue a refund, which is a new fact with its own record. This means some compensations are imperfect: an email cannot be unsent. Designing the sequence so irreversible steps happen last is the main mitigation.

How do you keep a saga from getting stuck?

Timeouts, persistence and idempotency. A Saga Pattern implementation must store its state so a crashed coordinator resumes rather than abandoning an order half-processed, apply a deadline to every step, and tolerate the retries that follow. Because retries are guaranteed at least once, each participant needs an idempotency key so a repeated instruction produces 1 effect rather than 2.

Related reading

Explore Custom ERP Solutions by Location, Industry, and Alternatives

Global Architectures