---
id: WF-COM-FUL-015
title: 'Hold, commit, pick and release stock for a buyer'
trigger: 'Checkout, placement, authorized delivery or release needs stock promises.'
product_area: commerce
module: fulfillment
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
implements:
  - CAP-COM-FUL-018
moves:
  - STATE-COM-FUL-009
crosses:
  - SVC-COM-FUL-inventory
  - SVC-COM-FUL-fulfillment
idempotency: >-
  Live checkout-unit holds and order-line unit claims have uniqueness
  constraints. Repeated picking returns existing picked work, and named fenced
  releases are repeatable.
concurrency: >-
  Hold selection locks sellable items in allocation order. Placement computes
  the needed claim, while constrained balances refuse competing overconsumption.
hops:
  - 'n': 1
    actor_or_service: Merchandise application (checkout preparation)
    action: >-
      Expire old SKU holds and retain the requested checkout-unit holds across
      sellable items within the product window.
    anchor: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:holdUnits
    seam: sync
    on_failure: Reject insufficient available stock and rollback the hold act.
    left_inconsistent: No partial refused hold remains.
    observer: Checkout availability result.
    provenance: observed
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts
  - 'n': 2
    actor_or_service: Orders placement (claim functions)
    action: >-
      Convert live holds or claim units at placement, retaining permitted
      backorders and releasing checkout ownership.
    anchor: 'services-commerce:modules/orders/services/placement/claims-at-placement.ts'
    seam: sync
    on_failure: Rollback placement on claim conflict.
    left_inconsistent: The failed placement keeps no new order allocation.
    observer: Placement conflict response.
    provenance: documented
    source: 'services-commerce:docs/migrations/inventory/README.md#D-P8I-04'
  - 'n': 3
    actor_or_service: Merchandise application (fulfil delivered by the register)
    action: >-
      Pick committed units under their delivery obligation and report progress;
      untracked goods can complete directly.
    anchor: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:pickUnitsOfLine
    seam: queue
    on_failure: >-
      Use delivery retry for transient paths; invalid unit ownership refuses
      permanently.
    left_inconsistent: Delivery can remain in flight until a valid outcome is applied.
    observer: Delivery attempt history.
    provenance: documented
    source: 'services-commerce:docs/migrations/inventory/README.md#D-P8I-06'
  - 'n': 4
    actor_or_service: 'Void, cancellation or nightly check'
    action: >-
      Release eligible units for expiry, void or the named cancellation and
      retain a release reason.
    anchor: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:releaseFencedUnitsOfLine
    seam: sync
    on_failure: Retry through the owning process where supported.
    left_inconsistent: Promises can outlive their intended release time.
    observer: Stale-allocation and expiry findings.
    provenance: observed
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:expireHolds
branches:
  - >-
    A backordered unit is committed later once stock arrives (movement
    workflow).
  - >-
    The availability read uses the existing rule for the storefront and the
    console.
waits:
  - Placement; authorization; the hold expiry.
evidence:
  - >-
    services-commerce at c8b66a98:
    modules/inventory/services/persistence/inventory-allocations.ts,
    inventory-items.ts; services/stock/sku-availability.ts;
    modules/merchandise/services/participant/merchandise-participant.ts;
    db/migrations/20261018024147_merchandise_and_inventory.sql;
    docs/migrations/inventory/README.md.
controls: [TC-IAM-006, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-CRY-001, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-004, TC-LOG-005, TC-AVL-004, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002]
---

# Hold, Commit, Pick and Release Stock for a Buyer

## What It Does

Checkout holds and placement claims retain one allocation per unit. Placement converts live holds or claims available stock, with backorders when allowed. Authorization picks committed units; cancellation, void and hold expiry release their eligible promises.

## The Flow

```mermaid
sequenceDiagram
  participant B as Buyer checkout
  participant M as Merchandise application
  participant A as Allocation ledger
  participant O as Placement claim
  participant R as Register
  B->>M: prepare (limited stock)
  M->>A: hold units until expiry
  B->>O: place
  O->>A: commit or backorder (one transaction)
  R->>M: fulfil the unit
  M->>A: pick under the obligation
  O->>A: void or cancel releases
```

## When Something Fails

Balance constraints refuse insufficient stock and roll back the owning claim transaction. Delivery retries retain unresolved allocation work. Released holds and shipped units use distinct paths, so physical returns do not reopen allocations.
