← Home
💬Real-life Scenario-based Interview QuestionsInterview QuestionsNEW
Important
Experience levelSenior · 5+ YOESenior / staff depth expected

An order has three items; the customer returns only one. Refund, payment capture, wallet credit, and inventory must stay consistent. How do you design this across services?

RefundsSagaPaymentsInventory

How I frame it

Partial return is a saga on a subset of order lines. Money, stock, and order line state must move together via compensable steps — never "refund API then hope inventory increments."

Domain model

  • Order lines: qty_ordered, qty_returned, qty_refundable.
  • return_requests(id, order_id, lines[], status, idempotency_key) — one return attempt is one saga.
  • Refund amount = sum(line price × qty × policy) − proportional tax/shipping rules.

Saga steps

  1. Validate: Line returnable (window, condition). Persist return APPROVED_PENDING.
  2. Restock (or quarantine): If sellable, inventory.credit(sku, qty, return_id) idempotent. If damaged → scrap warehouse bin, no sellable credit.
  3. Refund money: PSP refund or wallet credit with idempotency key = return_id. Partial capture/refund against original payment intent.
  4. Update order: Increment qty_returned; order status PARTIALLY_REFUNDED / CLOSED.
  5. Notify via outbox.
Return R88 line=SKU-A qty=1
  1. Validate ✓
  2. Inventory +1 (key R88)
  3. Refund ₹799 (key R88) → PSP
  4. Order line returned=1
If 3 fails after 2: compensate inventory −1 OR leave overstock + manual
  Prefer: money step before restock-for-sale if fraud high; warehousing ops dictate order

Failure rules

  • PSP refund UNKNOWN → do not mark return COMPLETE; reconcile; stock may stay in quarantine.
  • Never double-refund: unique return_id / refund idempotency at PSP.
  • Second return of same unit blocked by qty math on line.

Weak answer

"Call refund and inventory APIs from the controller with no saga state." Mid-crash leaves free money or phantom stock.

Follow-up questions

Promo / coupon on original order?

Recompute refund with same promotion engine rules; store snapshotted line discounts at order time — do not re-price at return with new catalog.

Exchange instead of refund?

Different saga: restock A + reserve B + net payment adjustment. Still one return_id / exchange_id.