Happy House - Ecommerce Docs
Developer ResourcesInventory

Inventory Module Overview

What the inventory module owns, the four generic operations, and what it deliberately does not know about.

Audience: Product owners, QA, frontend and backend developers Scope: Stock tracking, reservations, movements, and the admin surface

Inventory Module - Overview

1. What the module owns

Inventory tracks stock for products:

  • Stock levels — total and reserved quantities per variant (a product sold in three configurations has three stock rows), with availability derived by the database.
  • Reservations — time-boxed holds on stock (a cart hold, a checkout hold) with a full lifecycle.
  • Movement ledger — every change to a product's counters, append-only, in PostgreSQL, written in the same transaction as the change itself.
  • Configuration — per variant: whether stock is tracked, whether overselling is allowed, and the low-stock threshold.
  • Import/export — CSV import of stock adjustments and CSV export of the ledger, as background jobs.

2. The four generic operations

Every inventory operation is one of four shapes:

OperationMeaning
AdjustChange total_quantity by a delta (manual, import, or the reconciler)
ReserveHold a quantity for a caller, with a key and an expiry
Release / finalize / expireGive the units back, or commit them to a purchase
ReconcileAssert the counters match the reservations and the ledger, and repair drift with a correction movement

3. What it deliberately does not know about

Inventory does not model pricing, promotions, orders or payments. It has no opinion on what a reservation is for — a caller supplies a reservation_key and a TTL, and the module treats the hold generically. The checkout and cart domains will be built on top of it.

There is no customer-facing inventory endpoint. Stock reaches the storefront through the product response's inventory group.

4. The three rules that matter most

  1. available_quantity and stock_status are GENERATED columns. Application code cannot write them; PostgreSQL computes them from the counters. Availability cannot go stale because nothing can store a stale value.
  2. Negative quantities are legal, but only under overselling. A negative total_quantity means units owed, not a bug. The strict CHECKs are conditional on allow_oversell OR NOT track_inventory.
  3. Every counter change is one guarded UPDATE, never a read-then-write. rowCount = 0 means "refused" and is the only trustworthy way to learn there is not enough stock.

5. Page guide

PageRead it for
Features and flowsActor journeys, capability matrix, reservation lifecycle, business rules and diagrams
BackendArchitecture, data model, GENERATED columns, services, workers, cache, security
APIEvery endpoint, DTO, error code and integration note