Archive, unarchive & delete a product
Retiring a product has two paths. Archiving hides a product from active lists while keeping every record it touches — stock history, orders, FIFO layers — fully intact and reversible. Deleting removes the product and its owned data permanently, and SKU only allows it when nothing depends on the product. Most of the time you archive; you delete only clean, never-used records.
Before you begin
- Archiving or unarchiving requires the products.archive permission.
- Deleting requires the products.delete permission.
- On the mobile card view, the per-row Delete action appears only when you hold products.delete, and the Archive / Unarchive action needs products.archive. Each control is gated independently.
See the product permissions reference for the full matrix.
Archive a product
Archiving takes a product out of your active working set without destroying anything.
- Open the products list.
- On the product's row, select the Archive icon (the archive-box icon at the end of the row).
- Confirm in the dialog. Archived items can be restored later.
What happens:
- The product's archived_at timestamp is set to now.
- The archive cascades to every variation (child) of the product — all
variations get the same
archived_atso a matrix product and its children retire together. - An
archivedmodel event fires, so downstream listeners stay in sync. - Archived products drop out of the default list. Turn on the Archived toggle in the list footer to see them.
If the product is already archived, SKU returns a warning (already_archive) —
not an error — and changes nothing. Archiving is idempotent.
Unarchive a product
- In the products list, turn on the Archived toggle to reveal archived products.
- On the row, select the Unarchive icon (the archive-arrow-up icon). The same per-row control toggles between Archive and Unarchive based on the product's current state.
- Confirm. The item is restored to its active state.
Unarchiving clears archived_at on the product and all its variations, and
fires an unarchived event. Unarchiving an already-active product returns a
warning and does nothing.
To archive or unarchive many products at once, see bulk archive, unarchive & delete products.
Delete a product
Deletion is permanent and only succeeds when the product — and every one of its variations — is completely unused.
- From the products list on mobile, open the row's kebab (⋮) menu and select Delete. (Desktop rows expose only the archive/unarchive toggle; delete a single product from the mobile card menu, the product detail page, or the bulk delete flow.)
- Confirm. This action can't be undone.
If the product is deletable, SKU removes it and cascades the delete to all of its owned data inside a single database transaction:
- Product attribute values, kit/bundle components, and bundle-membership rows
- Listings, pricing, suppliers and supplier inventory, images
- Variations, the inventory cache, benchmarks, reporting rows, categories, blemished records, and eBay product settings
- Amazon-owned data — FIFO layers, merchant-SKU mappings, and pending inbound items — cleaned up through the Amazon module
Because the whole cascade runs in one transaction, if a database constraint the pre-check doesn't cover blocks the final delete, every child delete is rolled back — you never end up with a half-stripped, orphaned product.
Why a delete is blocked (and how to read the reasons)
Before deleting, SKU checks whether the product is used. If so, the delete is refused with HTTP 400 and a list of reasons — one per relationship that still references the product. The response message points you to archive the product instead.
A product is considered used when it (or any of its variations) is referenced by any of these records:
| Blocking relationship | What it means |
|---|---|
| Sales order lines | The product was sold on an order |
| Bundle sales order lines | The product was sold as a bundle — a distinct check, because a bundle sold via the sales order line's bundle_id would be missed by a plain product-id lookup |
| Purchase order lines | The product was ordered from a supplier |
| Inventory movements | The product has any stock ledger movement |
| FIFO layers | The product carries costed stock layers |
| Inventory adjustments | Stock was manually adjusted |
| Inventory assembly lines | The product was built or consumed in an assembly |
| Warehouse transfer lines | The product moved between warehouses |
| Return receipt lines / RMA lines | The product appears on a return or RMA |
| Sales credit lines | The product appears on a credit |
| Blemished products | A blemished product was derived from it |
| Inbound shipment lines | The product is on an inbound shipment |
| Subscription editions | The product is tied to a subscription edition |
Each of these maps to a foreign key that restricts deletion. Keeping the used-check aligned with those keys is what makes the deletability preview truthful: a product referenced by (for example) a FIFO layer or an inbound shipment line is reported as not deletable up front, rather than passing the preview and then failing mid-delete.
When any of these apply, archive the product instead. Archiving preserves all the history that blocked the delete while removing the product from your active lists.
Run the pre-flight deletability check
Before attempting a delete — especially in bulk — you can ask SKU whether one or more products can be deleted and, if not, exactly what's blocking each one.
Send the product IDs to the is-deletable endpoint
(POST /products/is-deletable). For each product it returns:
- deletable —
trueonly when nothing references the product or its variations. - usages — one entry per blocking relationship, each with:
- a friendly label (for example, Sales Order Lines, Purchase Order Lines),
- a count aggregated across the product and all its variations, and
- up to ten sample records — sales-order and purchase-order numbers, inventory-movement types, or the parent SKU for bundle membership — so you can trace where the product is used.
The bulk delete flow uses this check to split your selection into deletable and archive-only products before you commit.
Edge cases when a product carries stock or open orders
Deleting and archiving behave predictably around inventory, but a few related guards are worth knowing:
- Delete silently becomes "must archive." The delete routine runs the used-check first. If the product (or any variation) has sales-order, bundle-sales-order, purchase-order, or inventory-movement records, the delete is refused with reasons rather than executed — SKU never destroys a product that has real history.
- Archive is always available and idempotent. Archiving sets
archived_at, cascades to variations, and returns a harmless warning if the product is already archived. It's the safe fallback whenever a delete is blocked. - Converting an inventory-bearing product to a non-inventory type is blocked. Changing a stocked product (standard, kit, blemished, manufactured) into a bundle or matrix is refused if the product carries any inventory ledger — a FIFO layer or an inventory movement of any type, including stock-take and receipt. This is broader than the sale/assembly only movement check: a product established purely by a stock take still has a ledger and is protected from a conversion that would orphan its FIFO layers. See convert & auto-detect product types.
- Kit components lock once the kit has moved. Editing the components of a kit that already has inventory movements is rejected — you can't silently rewrite what a stocked kit is made of. See build bundles & kits in the Workshop.
For anything to do with the stock numbers themselves — on-hand, allocations, FIFO cost layers, or opening balances — see view a product's stock and browse FIFO layers.
Per-row actions at a glance
| Surface | Archive / Unarchive | Delete | Notes |
|---|---|---|---|
| Desktop table row | Icon toggle (Archive ↔ Unarchive) | — | Permission-gated on products.archive |
| Mobile card kebab (⋮) | Needs products.archive | Needs products.delete | The menu always offers View (open the detail page); Archive/Unarchive is gated on products.archive and Delete on products.delete, independently |
| Mobile card | — | — | Archived products show a grey Archived pill |
Next steps
- Bulk archive, unarchive & delete products — retire or delete many products at once with the same deletability guards.
- Browse, search & filter the products list — find products and toggle archived visibility.
- Merge duplicate products — the right tool when two records describe the same item and delete is blocked.
- Convert & auto-detect product types — understand the inventory-ledger guard on type changes.