Skip to content

help wanted: harden inventory against concurrent overbooking (Bug 5 / SERIALIZABLE) #306

Description

@telivity-otaip

Why hotels care

A full house with a walk-in at the desk and a Booking.com / direct-widget booking landing at the same second is a classic PMS failure mode. Hotels do not forgive silent double-sells — one room sold twice means a walk, a voucher, a review bomb, and a GM on Discord.

HAIP already wraps availability check + insert in a transaction, but Postgres stays at READ COMMITTED. The code itself calls this out as Bug 5.

Current state (code anchors)

  • apps/api/src/modules/reservation/reservation.service.ts — create + date/type modify paths note TOCTOU and say: "for stronger guarantees promote to SERIALIZABLE… see Bug 5"
  • Conditional state-machine claims (Bug 2) are already solid — this issue is specifically inventory capacity, not status races
  • Inbound OTA + booking-engine + PMS create all hit availability; they need the same guarantee

What we need

A production-safe way to make concurrent sells fail closed when the last room is contended:

  1. Prefer SERIALIZABLE (or an equivalent inventory lock / constraint) on the availability+write critical section
  2. Prove drizzle-orm + postgres-js behavior under SERIALIZABLE (retries on serialization failures)
  3. Cover create, modify (dates/room type), Connect booking, and booking-engine paths
  4. Load / concurrency tests that would fail today under READ COMMITTED

Open questions (hotel / domain — comment if you run a property)

  • When the race loses, should the desk see a dedicated inventory_conflict error (vs generic "no availability")?
  • Should overbooking agent allowance interact with this lock, or only physical capacity?

Do not invent overbooking product rules here — stick to "never sell more physical inventory than exists unless the overbooking path explicitly allowed it."

Acceptance criteria

  • Two concurrent creates for the last room: exactly one succeeds, one gets a clean 4xx
  • Same guarantee on stay modify that expands dates / changes room type
  • Serialization / lock failures retry safely or surface as conflict (no 500s, no phantom inventory)
  • Vitest (or integration) concurrency coverage; docs note the isolation choice
  • No invented hotel domain — only capacity integrity

How to contribute

Ideal for someone who has fought inventory races in a PMS, booking engine, or high-contention Postgres app.

  1. Comment to claim
  2. Reproduce the race locally (two parallel POST /reservations against last room)
  3. PR with tests first, then the isolation/lock fix
  4. Tag maintainers before changing global transaction defaults

Search keywords: overbooking, double booking, inventory race, SERIALIZABLE, TOCTOU, last room, channel + walk-in

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthardeningPost-v1.0 production hardeninghelp wantedExtra attention is needed

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions