Ask a furniture retailer how many oak dining tables they have in stock, and the honest answer isn’t a single number. It’s a list: one on the showroom floor, two in a warehouse bin, one riding in a delivery truck, and one sitting in the back with a scratched leg waiting on a repair ticket. A quantity field can only hold “5.” It can’t hold where each of those five actually is, or which one shouldn’t be sold as new.
That gap is where a lot of furniture retail software quietly breaks.
What a count actually tracks
Most inventory systems store a SKU and an integer: 12 units of “Oakwood Dining Table, walnut finish.” Every sale decrements the integer, every restock adds to it. This works fine when the units behind that integer are interchangeable: cans of soup, t-shirts in the same size, anything where one unit is functionally identical to the next.
Furniture doesn’t stay interchangeable once you look past the SKU. Two chairs with the same SKU can have different histories: one came straight from the vendor, one was a showroom floor sample handled by hundreds of customers, one got returned with a chip in the veneer. On paper they’re the same product. In the warehouse they’re different assets.
Why the integer lies
The problem shows up first at returns. A customer sends a sofa back. A quantity system’s job is simple: add 1 back to “Sofa, oatmeal.” But that specific sofa might have a torn cushion or a broken frame, and it isn’t safe to sell as new stock. If the only record is a count, the system has no way to know the 13th sofa in inventory isn’t the same as the other 12.
Repairs cause the opposite failure. A unit goes out for warranty work and the count drops, even though the physical item still exists. It just isn’t sellable right now, and a plain count can’t distinguish “gone” from “temporarily unavailable.” Deliveries and showroom transfers add a third wrinkle: the same SKU has to stay trackable while it physically moves between a warehouse, a showroom floor, and a customer’s home, and staff need to know which exact unit is where for insurance, damage claims, and delivery routing. A schedule that assigns trucks and drivers to routes has to know which specific unit sits on which truck each day. A shipped-units count can’t answer that.
Purchase orders push the same problem upstream. When a shipment of chairs arrives from a vendor, a quantity system just adds to a number. Receiving is where the identity of each unit should start instead: this chair came in on this purchase order, from this vendor, on this date. If part of a shipment turns out damaged or doesn’t match what was ordered, someone has to trace the problem back to specific units, and a count field gives them nothing to trace with.
None of this is a counting problem. It’s an identity problem. Quantity tracking answers “how many.” Furniture retail needs an answer to “which one, where, and in what condition.”
What serialized tracking requires
The fix is to give every physical unit its own record instead of letting a SKU absorb all of them into one number. Each unit gets a serial number at intake, and that serial carries a location and a status through the unit’s whole life in the business, from intake through to disposal or resale. Roughly the shape of it:
model InventoryUnit {
id String @id @default(cuid())
serial String @unique
skuId String
locationId String
status UnitStatus
}
enum UnitStatus {
AVAILABLE
RESERVED
NEEDS_REPAIR
SOLD
}
A return now moves that specific serial to NEEDS_REPAIR, and the unit stays out of sellable stock until someone changes that status on purpose, rather than silently padding a count back up. A delivery reassigns a serial’s location from warehouse to a customer address and marks it SOLD. The system always knows which physical object it’s talking about.
The status field carries as much weight as the serial itself. A unit moving from AVAILABLE to RESERVED to SOLD leaves a trail that answers questions a plain count never could: which unit has sat in a warehouse the longest, which serials came off a specific vendor shipment, which unit is loaded on which delivery truck this morning. None of that is optional once returns, repairs, and transfers between locations are routine rather than exceptions.
Where this actually shows up
FurnitureAxis is built around this: serialized per-unit inventory tracked across warehouses, showrooms, and bins, not a quantity field per SKU. Its purchase orders carry receiving and shipment tracking down to those same units, and delivery scheduling assigns trucks and drivers to routes built around where each unit sits on a given day. That’s a direct consequence of the business it runs. A retailer moving big-ticket furniture between multiple locations, with a showroom floor, a delivery fleet, and a repair process, needs the system to answer “where is this specific piece right now” as often as it answers “how many do we have.”
What we weigh when a client asks
Serialized tracking isn’t free. Every unit needs a serial applied at intake, staff need to scan or log status changes as units move, and the data model carries more weight than a plain quantity column. For a retailer selling high volumes of cheap, interchangeable stock, that overhead buys nothing. A quantity count is the right tool there, and per-unit tracking would just slow the floor staff down.
The calculation flips once the average unit price rises and returns or repairs become common enough to matter. Furniture, appliances, and anything sold as a distinct physical object rather than an interchangeable commodity usually belongs on the retail and POS side of that line, and the back office running it starts to look less like a storefront and more like an ERP and operations problem: purchase orders, receiving, and delivery scheduling, all tied to the same per-unit records.
If your inventory system currently answers “how many” and your business needs it to answer “which one,” that isn’t a small config change. It’s a different data model, built around identity instead of count. Get in touch if you’re trying to figure out which side of that line your business is actually on.