Skip to content

Safety-stock reservations

A safety-stock reservation lets you declare “at this location, keep enough raw materials to build N units of this BOM (or sub-assembly).” Assemblified resolves the recipe, deducts the required components from available stock, and tracks the hold so you can release it later — either restoring the raws to available, or converting them into finished pre-assembled stock.

This is useful when a fulfilment commitment depends on having stock buildable on demand: wholesale contracts, retail buffers, planned production runs. Without a reservation, a sudden flurry of normal orders could drain the components your buffer depends on.

  • What a reservation is
  • Creating, editing, and releasing
  • The two release modes
  • How Shopify-managed vs virtual materials behave
  • The “Reserved as safety stock” surface on raw materials
  • Failure handling and the retry button
  • Edge cases & gotchas

A reservation has three parts:

  • An owner — a BOM or a Sub-Assembly.
  • A location — exactly one location per reservation.
  • A target unit count“keep enough raw materials to build this many.”

There is at most one active reservation per (owner, location). Editing a reservation mutates that row in place — you don’t pile up multiple reservations for the same BOM at the same warehouse.

The components the reservation actually holds are derived by recursive recipe expansion — sub-assemblies are expanded down to raw materials, waste percentages are applied. The resolved component list (the “plan”) is stored as a snapshot at write time, so a release later reverses exactly what the create reserved, even if the BOM’s composition has changed in the meantime.

The Reservations tab is on both the BOM detail page and the Sub-Assembly detail page.

  1. Click “Add reservation.” A dialog opens.
  2. Pick a location and a target unit count.
  3. Optionally add a reason — free text, surfaced in the audit log.
  4. Review the preview. The dialog shows exactly which raw materials will be deducted, at what quantities, and flags any shortages.
  5. Confirm. Available stock drops by the resolved amounts; Shopify-managed materials move from availablesafety_stock in Shopify’s native bucket; virtual materials decrement on the Assemblified side.

If any required material is short at the target location, the preview shows the shortage and the Confirm button is disabled. Increase the underlying stock or pick a different location.

Click an existing reservation’s “Edit” action. You can change the target unit count and the reason. Location is locked — moving a reservation between locations requires releasing it and creating a new one (this avoids accidentally creating two active reservations for the same scope).

Behaviour by direction:

  • Edit up (target increases) — the additional component quantities are deducted from available stock.
  • Edit down (target decreases) — the freed component quantities are restored to available stock. This uses the same release-globally machinery as a full release.

Two release modes, picked from the reservation card menu:

Reverses the reservation. Every held component returns to available stock — Shopify-managed materials move safety_stockavailable; virtual materials’ available is incremented and a history row is written. The reservation row is preserved (status released, releaseMode: global) for audit history.

Use when the planned demand evaporated or you no longer need the buffer.

The held raw materials are considered definitively consumed — they don’t return to available. The BOM’s pre-assembled inventoryPre-Assembled InventoryStock of finished sub-assemblies and BOM items that have already been built and are sitting on the shelf. When a work order needs a sub-assembly, it draws from pre-assembled inventory first and only builds fresh ones if the shelf comes up short. Read more → for that location increments by the target unit count. For BOMs with a Shopify variant, the variant’s Shopify available is also pushed up — your storefront immediately reflects the new buildable units.

This is essentially “the reservation is now built.” Use when you’ve actually finished the production run that the reservation was holding components for.

Available for sub-assembly reservations too — the sub-assembly’s pre-assembled shelf increments. Sub-assemblies typically don’t have a Shopify variant, so the Shopify push is skipped.

Material kindOn reserveOn release-globalOn convert-to-preassembled
Shopify-managedShopify availablesafety_stock (via inventoryMoveQuantities)Shopify safety_stockavailableShopify safety_stock decrements (consumed); BOM variant available increments
Virtual (Assemblified-only)virtual_inventory_levels.available decrements; audit row writtenavailable increments; audit row writtenAudit row written (zero-delta disposition); available already deducted at reserve

Effective-available semantics stay correct everywhere. Build-run pre-checks, BOM availability displays, dynamic adjustment, and the storefront all read the same available columns — and those columns have already been decremented by the active reservation. You don’t need to subtract reservation amounts in your head; the system has already done it.

The Raw Material detail page has a “Reserved as safety stock” column per location, aggregated across all active reservations that consume this material. Hover for the breakdown (which BOM, at which location, how much).

This is read-only — to change the reserved amount, edit the reservation that produced it.

Shopify-side mutations can fail (rate-limited, session expired, mid-flight network drop). When they do:

  • The local reservation tables still commit — the operator-facing intent is preserved.
  • The reservation card shows a “Has Shopify failures” badge.
  • Per-line status flips to failed with the error captured.
  • A “Retry Shopify sync” button appears on the card.

Clicking retry replays the Shopify mutation for just the failed lines. Successful lines aren’t re-pushed. Recovery from a full retry clears the badge.

  • Location is fixed for active reservations. The Edit dialog disables the location selector. To move a reservation between locations, release it and create a new one.
  • Edit-down freed inventory is non-discretionary. The freed materials return to available immediately — the reservation can’t “park” a partial release.
  • Convert-to-preassembled is one-way. See the caution above.
  • A failed Shopify push leaves the system de-synced until you retry. Use the per-card “Retry Shopify sync” button. The dedicated retry endpoint is the recommended recovery path — re-editing the reservation also fixes it but is the long way around.
  • Sub-assembly reservations recurse. A reservation on a sub-assembly that itself contains sub-assemblies expands down to raw materials. The reservation owns the resolved component list; intermediate sub-assemblies are not “reserved” as preassembled.
  • Per-material location override. If the BOM’s recipe pins a material to a specific location (not the reservation’s default), the reservation honours that pin — the component is deducted from its designated location, even if it differs from the reservation’s header location.
  • Audit history is permanent. The safety_stock_reservation_log table keeps every event: created, target changed, released globally, converted to pre-assembled, Shopify synced, Shopify sync failed. The reservation card surfaces the log so operators can trace what happened.