Checkout inventory holds (Cryo-Lock)
When Web Store and inventory tracking are enabled, Eonix can hold stock for a short window while a visitor completes Stripe Checkout. The hold starts when they click through to pay — not when they add items to the cart.
This prevents two shoppers from both reaching payment for the last unit on hand. Holds are temporary; they clear when the order is paid, cancelled, or when the hold expires (default about 10 minutes).
Your operator turns the feature on in server configuration (ES_CRYO_ENABLED on engine and platform, plus NATS on the engine). Creators do not toggle it in the desk.
What staff see in Products
On a physical product with tracked inventory:
- On hand — Quantity from the inventory ledger (receipts, adjustments, sales after payment).
- Reserved — Quantity tied to open checkout holds (not ledger rows). Shown on the product editor and list when cryo is active.
- Sellable — On hand minus reserved (what new checkouts may still claim).
After someone starts checkout, reserved rises until they pay, cancel, or the timer runs out. Use Ledger travel for historic ledger balances; reserved is always “right now” from the hold layer.
What shoppers see
- Product page — While a hold cookie is active for their browser session, the stock block can show a countdown (for example “Reserved for checkout — complete payment within 8:42”).
- Cart / checkout — After a successful checkout start, they may see a brief “Stock held while you pay” message before redirect to Stripe.
If checkout returns insufficient stock (HTTP 409), another session (or an expired hold that has not yet cleared) already claimed the available units. Ask the shopper to retry in a minute or reduce quantity.
When holds are placed and released
| Event | Hold behaviour |
|---|---|
| Add to cart | No hold — cart is browser LocalStorage only. |
POST /public/api/commerce/checkout | Hold placed for tracked lines (needs Stripe Connect + Web Store). |
| Payment succeeds | Hold released; ledger posts the sale (DirectionOut). |
| Order cancelled | Hold released. |
| Timer expires | Hold drops; reserved count and storefront stock update without staff action. |
Webhooks and live stock
Subscribe to commerce.inventory.adjusted on Observe → Webhooks when partners need the same snapshot the desk uses:
| Field | Meaning |
|---|---|
available | Sellable-style count after the event (ledger minus active holds). |
reserved | Units held for in-flight checkouts. |
Related commerce events: commerce.order.placed, commerce.order.paid, commerce.order.cancelled, commerce.product.updated.
Public SSE on product pages (commerce:<slug>) uses the same available / reserved fields after engine fan-out.
Reconciling orders
Staff answering “did they get the last one?” should use Exchange for order state and Products for current on hand / reserved — not the payment provider alone.
- Paid — Hold gone; on hand reduced by the sale.
- Awaiting payment — Reserved may still include their line until TTL or completion.
- Two people, one unit — First checkout gets the Stripe URL; second gets 409 oversold.
Troubleshooting (creators)
| Symptom | What to check |
|---|---|
| No countdown on the live site | Cryo may be off; product may not track inventory; visitor may have no active checkout session. |
| “Insufficient stock” at checkout | Sellable is 0 — another checkout holds stock or on hand is 0. Wait for hold TTL or adjust ledger after confirming no open order. |
| Reserved stuck high | Open awaiting-payment orders or slow TTL; operator can inspect engine cryo KV / order list. |
Webhook reserved always 0 | Cryo disabled, or event fired only on ledger change with no holds active. |
Operators: see repository docs/dev/cryo-lock-inventory.md and ./scripts/validate_cryo_hold.sh in the platform tree for enablement and smoke tests.
Related
- Products — catalogue, inventory adjustments, sale windows
- Exchange — order pipeline for staff
- Webhooks and events — outbound commerce payloads
- Ledger travel — historic ledger stock (not reserved-at-checkout)
- Troubleshooting — sale price and stock on the live site