At a glance
Real-time alert that fires when more than 5 enabled-and-visible Adobe Commerce SKUs transition to zero salable quantity within a 1-hour window. Designed to catch the supplier-stall pattern (a vendor stopped shipping a category), the warehouse-receive failure (a pallet arrived but never got booked into MSI), or the catalogue-import bug (a CSV upload accidentally set quantity to zero). Five SKUs simultaneously is rarely coincidence; it is almost always systemic.
Calculation
Calculated automatically from your Adobe Commerce data. See the At a glance summary above for what the metric tracks and the worked example below for a typical reading.Worked example
A specialty footwear brand on Adobe Commerce 2.4.6 with US, UK, and B2B Store Views. The merchant runs about 1,800 enabled SKUs across 240 product families. Snapshot taken Wednesday 14 Apr 26, 10:00 GMT. The alert just fired. SKUs that flipped to zero salable_qty in the last hour:
7 SKUs flipped to zero in 1 hour. All are Wellington Boots variants. Five of seven are size 9 to 11, which are the most commonly-stocked sizes.
What the investigation reveals:
- The pattern is unmistakable: an entire product family went out of stock simultaneously. This is rarely demand-driven.
- Last-hour orders against the affected SKUs total 14, against a typical 90-orders/week baseline for the family. Demand explains the flip on the size 10 black (6 orders × 3 typical inventory units = depleted), but it does NOT explain the green and navy SKUs flipping with zero recent orders.
- Adobe admin > Catalog > Products > [BOOT-WL-GRN-11] > Quantity tab: shows
qty = 5at UK source. Butsalable_qty = 0. That’s the smoking gun. - Cross-checking Order State Distribution: 28 orders entered
pending_paymentin the last 90 minutes (vs a typical 4 per hour). MSI reserved stock for all 28; on these slow-moving variants, the reservations exhausted available salable_qty. - Root cause: the merchant’s payment gateway (Stripe Connect) is silently failing webhook callbacks since 09:00. Orders are being created in
pending_payment, MSI is reserving stock, but the orders are not transitioning toprocessing. After ~25 minutes the customer typically tries again, creating a duplicate order and another stock reservation. - The fix: replay the failed Stripe webhooks (Stripe Dashboard > Developers > Webhooks > Failed deliveries > Resend). Within 5 minutes the orders move to
processing(real stock decrement) orcanceled(release the MSI reservation). The “OOS” SKUs return to positive salable_qty automatically. - Without this card the merchant would have: paused the Wellington Boots ad campaign (avoiding ~$340/day waste, fine), restocked from the supplier (unnecessary, the stock was always physically present), and only discovered the gateway issue when revenue dropped enough to trip the Revenue Drop Alert about 3 hours later.
Sibling cards merchants should reference together
This alert is most informative when paired with order-state and ad-spend cards.Reconciling against the vendor’s own dashboard
Where to look in Adobe Commerce Admin: For the live OOS list:Catalog > Products with filter Quantity ≤ 0 and Status = Enabled and Visibility != Not Visible Individually gives the candidate list. Adobe Admin shows physicalFor Multi-Source Inventory (MSI) detail:qty, notsalable_qty; for the salable view you need to click into each product and check the Sources tab.
Stores > Inventory > Sources to see your configured stock-sources, then Stores > Inventory > Stocks to see the source-to-website mapping. A SKU’sFor reservations:salable_qtyis the sum of its source-levelqtyminus reservations, across all sources mapped to the website.
Reservations are not directly visible in Admin; they exist in theOther Adobe Commerce Admin views that look relevant but are not:inventory_reservationtable. Usebin/magento inventory:reservation:list(CLI) or query the table directly to see active reservations against a SKU.
- Reports > Products > Low Stock: based on the merchant-configured low-stock threshold (typically 1 or 5 units), not zero.
- Catalog > Categories: hierarchy, no live stock signal.
- Stores > Configuration > Catalog > Inventory: configuration, not state.
Cross-connector reconciliation (when these connectors are connected for this merchant):
Known limitations / merchant FAQs
The alert fired but my warehouse confirms stock is on the shelf, why? Most common cause: MSI reservations againstpending_payment orders. A burst of pending-stuck orders (gateway callback failure) reserves stock in MSI without taking payment. The salable_qty drops to zero even though physical stock is healthy. Cross-check Order State Distribution for a pending_payment spike. The fix is to resolve the gateway callback backlog, not to restock.
What’s the difference between qty and salable_qty and why do they disagree?
qty is the physical-source stock count (what’s on the warehouse shelf, per source). salable_qty is what’s available to sell after subtracting active reservations (orders in pending_payment and processing that haven’t shipped). A SKU with qty = 10, reservations = 10 shows salable_qty = 0 and is correctly flagged as OOS for storefront purposes; a customer cannot actually buy it.
Adobe Commerce vs Magento Open Source: any difference for this card?
MSI ships in both editions from Magento 2.3 onwards. The difference: Adobe Commerce edition adds a richer Inventory Management UI and the Source Selection Algorithm for multi-warehouse orders; Open Source has the same underlying tables. The card works identically on both.
My multi-source Adobe Commerce, the SKU is OOS at one warehouse but in stock at another, why is it flagged?
The card uses aggregate salable_qty across all stock-sources mapped to the website. A SKU at zero across all sources is OOS storefront-wide. If it is zero at one source but positive at another, the storefront still shows it as available and it is NOT flagged. For region-locked operations (UK warehouse only ships UK), set up per-Stock variants in the manifest so the card respects the source-to-website routing.
Why exclude configurable child SKUs?
Configurable products in Adobe Commerce work as a parent SKU with child variants per option (e.g. parent BOOT-WL-BLK with children BOOT-WL-BLK-7 through BOOT-WL-BLK-12). The parent itself is a virtual SKU; only children have stock. The card counts the parent as “OOS” only when ALL its child variants are zero, otherwise the parent still shows as buyable on the storefront. Counting individual children would over-fire (one size out of stock is normal); counting only fully-OOS parents is the right granularity.
The threshold of 5 SKUs feels arbitrary, can I change it?
Yes, configure in the manifest. For very large catalogues (50,000+ SKUs) raise to 20 or 50; for very small catalogues (under 200 SKUs) consider lowering to 3. The point is a count high enough to filter routine variance and low enough to catch systemic issues early. The 5-SKU default suits a typical 1,000 to 5,000 SKU mid-market catalogue.
Why doesn’t my low-stock report show the same SKUs?
Adobe Commerce’s “Low Stock Report” uses the merchant-configured low-stock threshold (default 1 or 5 units, set per-product or globally). It is a forecasting view (which SKUs to reorder), not an alarm view (which SKUs just went OOS). The two views overlap but ask different questions.
My multi-store Adobe Commerce, can I get per-Store-View OOS counts?
Yes, configure per-Store-View variants. Useful for merchants whose Store Views correspond to different warehouses or regional catalogues. Without per-Store-View variants, the card aggregates across all Store Views which can mask region-specific patterns.
The Adobe Commerce Inventory Management UI shows the SKU qty = 0 but is_in_stock = true, why is it flagged?
Likely cause: the merchant-configured Out-of-Stock Threshold is negative (e.g. -10), allowing oversell. Adobe still considers it “in stock” until the threshold is crossed. The card detects the salable_qty hitting zero, which represents the customer-facing reality (no units to claim). If oversell is intentional, configure the manifest to skip SKUs where backorders = 1 or out_of_stock_threshold < 0.