|
Studying the FreshCart architecture and want to understand the saga implementation across ordering and payment. Specific questions:
Building something similar and want to understand the trade-offs. |
Replies: 1 comment
|
Great questions — these are exactly the trade-offs that cost teams the most time to get right in microservices. Here's how FreshCart handles each: 1. Coordinating stock reservation → payment → confirmation (and rollback on failure)FreshCart uses a choreography-based saga via MassTransit + RabbitMQ. The sequence is: On payment failure: No 2PC. No centralized orchestrator. Each service reacts to what happened and publishes what it did. The saga state is implicit in the order's status transitions and in each service's own domain state. 2. Why Transactional Outbox instead of 2PC or orchestration?2PC is a non-starter in microservices because it requires a distributed lock coordinator and makes every participating service synchronously available — one network hiccup during the prepare phase blocks the transaction forever. It turns O(1) availability into O(N) availability. The Transactional Outbox solves the problem at the source: the service writes to its own DB and its outbox table in a single local ACID transaction. A background processor (OutboxProcessor : BackgroundService in FreshCart) polls the outbox and publishes messages to RabbitMQ after the fact. The guarantee becomes: "the DB write succeeded ↔ the event will eventually be published" — no dual-write failure possible. Why choreography over orchestration? Orchestration (a dedicated saga coordinator service) adds a single point of failure and couples all services to the coordinator's contract. Choreography keeps services fully independent — InventoryService has no idea PaymentService exists. The trade-off is that the overall saga flow lives in event schemas rather than a visible process definition, so debugging requires correlating events by correlationId (which FreshCart logs via OpenTelemetry tracing). 3. Consumer idempotency — preventing duplicate effectsFreshCart uses a two-layer approach: Layer 1 — MassTransit's built-in deduplication: Consumers implement Layer 2 — Domain-level idempotency guards: Even without the inbox, the domain model enforces it:
This means double-delivery is harmless: the inbox catches it first, and if somehow the inbox check were bypassed, the domain guard is the second gate. Summary of the key trade-offs:
Hope this helps! Feel free to follow up if you want more detail on any specific part of the saga flow. |
Great questions — these are exactly the trade-offs that cost teams the most time to get right in microservices. Here's how FreshCart handles each:
1. Coordinating stock reservation → payment → confirmation (and rollback on failure)
FreshCart uses a choreography-based saga via MassTransit + RabbitMQ. The sequence is:
On payment failure: