The double-booking problem
Two customers hit "Book" on the last available room within the same 50ms window. A naive flow reads availability, sees one room, and writes two reservations. The fix is not a bigger database. It is modelling the hold as an atomic operation.
Atomic admission
We use an atomic Redis admission step before any reservation is written:
// Decrement only if inventory remains; returns the remaining count or -1.
const remaining = await redis.eval(HOLD_SCRIPT, [inventoryKey], [holdId, ttl]);
if (remaining < 0) throw new NoInventoryError();
The Lua script runs single-threaded inside Redis, so two concurrent requests can never both succeed against the last unit.
Event-sourcing the reservation
The reservation aggregate is event-sourced: HoldPlaced → PaymentAuthorized → ReservationConfirmed. The read model is a projection you can rebuild at any time, never the source of truth. This is what makes the audit trail trustworthy.
Takeaway
Correctness under concurrency is a design property, not a patch. Model the contended resource explicitly, make the contended step atomic, and keep your source of truth append-only.