Skip to main content

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.

  1. Open the products list.
  2. On the product's row, select the Archive icon (the archive-box icon at the end of the row).
  3. 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_at so a matrix product and its children retire together.
  • An archived model 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.
Re-archiving is harmless

If the product is already archived, SKU returns a warning (already_archive) — not an error — and changes nothing. Archiving is idempotent.

Unarchive a product

  1. In the products list, turn on the Archived toggle to reveal archived products.
  2. 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.
  3. 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.

  1. 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.)
  2. 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 relationshipWhat it means
Sales order linesThe product was sold on an order
Bundle sales order linesThe 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 linesThe product was ordered from a supplier
Inventory movementsThe product has any stock ledger movement
FIFO layersThe product carries costed stock layers
Inventory adjustmentsStock was manually adjusted
Inventory assembly linesThe product was built or consumed in an assembly
Warehouse transfer linesThe product moved between warehouses
Return receipt lines / RMA linesThe product appears on a return or RMA
Sales credit linesThe product appears on a credit
Blemished productsA blemished product was derived from it
Inbound shipment linesThe product is on an inbound shipment
Subscription editionsThe 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:

  • deletabletrue only 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

SurfaceArchive / UnarchiveDeleteNotes
Desktop table rowIcon toggle (Archive ↔ Unarchive)Permission-gated on products.archive
Mobile card kebab (⋮)Needs products.archiveNeeds products.deleteThe menu always offers View (open the detail page); Archive/Unarchive is gated on products.archive and Delete on products.delete, independently
Mobile cardArchived products show a grey Archived pill

Next steps

Last verified: