Most stock systems store a number and overwrite it. Receive goods, the number goes up. Pick an order, it goes down. The problem: the moment two things happen at once — a return, an adjustment, a transfer — that single number drifts, and you can't tell why.
The append-only alternative
Event sourcing flips the model. Instead of storing a position, you store every event that changes it:
GoodsReceived(with batch, expiry, quantity)StockReserved(against an order)StockPickedStockTransferredAdjustmentMade(with reason and approver)
The position is derived by replaying those events. Nothing is overwritten; nothing is lost.
Why this matters operationally
If an auditor asks "why does bin A3 show 240 units?", an event-sourced ledger answers with the exact sequence of receipts, picks and adjustments that produced it.
Three concrete wins:
- Reconciliation becomes replay. Any position can be audited back to its cause.
- Batch and expiry are first-class. FEFO allocation is reliable because every unit carries its batch.
- Adjustments are visible. Shrinkage and damage are events with reasons and approvers — not a silent edit to a cell.
The trade-off
Event sourcing is more work to build than a mutable number. But for FMCG — where batch, expiry and returns are constant — it's the difference between counts you trust and counts you hope are right.
This is how the Inventory module works under the hood, and it's what lets procurement GRNs write stock you can stand behind.