Get a quote
E-commerce

Modelling product variants: which record holds price and stock?

One scent ships in several sizes, one car in several trims, every used machine is one of a kind. Four live catalogues answer the same question differently: which record holds price and stock?

Algoriel 15 min read
Modelling product variants: which record holds price and stock?
In this article
  1. The variant boundary is the first decision in a catalogue
  2. The sellable-unit test: what do price and stock attach to
  3. When two axes meet, the record is the combination
  4. A variant record holds more than a price
  5. A browsing axis is not a variant
  6. When every unit is unique, there is no variant model
  7. Where each distinction goes: four approaches side by side

A product variant is a sellable unit carrying its own price and stock beneath a shared product record, which holds neither. Where the line between product and variant runs is settled before any screen exists, by asking whether a separate price and stock figure hang on the distinction. The reverse holds too: no price hangs on a fragrance note, so modelling it as a variant would open a stock counter nobody could ever fill.

The variant boundary is the first decision in a catalogue

The earliest decision in a catalogue is what counts as a record. This is not a screen preference to be revisited later; it is the ground that price, stock and orders get written onto. Choose the ground badly and the mistake does not surface in one place. It spreads, and it shows up later as a dozen small inconveniences that nobody traces back to a data model.

Perfume retail puts the decision in plain view. In the Kokudankokuya store, where one scent sells in several bottle sizes, the standard e-commerce product model sees one perfume as one row. The shop does not work that way. Nobody buys a fragrance in the abstract; a customer buys a particular bottle of it.

An off-the-shelf setup offers two ways through that knot, and each carries its own bill. The first is to open every bottle size as an independent product. The data holds up, and the catalogue falls apart. The same perfume lines up one after another on the listing page, a search returns the same name several times over, and a shopper can only work out how many forms of one product exist by reading the rows. The wider the range, the louder the repetition gets.

The second is to compress every size into a single product record. Now the catalogue looks tidy and the record falls apart. Price sits in one field, and the difference between sizes drops into a line of description text. Stock is where it hurts most. Nothing in the record says which bottle ran out, because the counter lives on the fragrance and there is only one of it. The person in the stockroom may know the answer perfectly well; the catalogue has no way to state it.

What the two ends have in common is that both push the problem outside the record. One pushes it into the shape of the listing, the other into somebody’s memory. The right boundary sits between them, and what places it is not a question of taste.

The sellable-unit test: what do price and stock attach to

Here is the test. Whatever has its own price and its own stock tracked separately is the sellable unit, and that is where the variant boundary runs. The useful question to ask is: does this thing carry a price and a stock figure of its own?

In Kokudankokuya the answer is the bottle size. The fragrance itself sits in the catalogue as a single record, and each size beneath it is a unit that sells on its own terms. Price and stock are written on those units rather than on the fragrance. The fragrance record works as an umbrella: it has a name, a description and an image, and it has neither a price nor a stock figure.

The difference shows most clearly when the range grows. A new bottle size does not open a new product. A unit is added beneath the umbrella that already exists. The number of products in the catalogue holds still while the number of sellable units rises. When the model is right, growth costs nothing on the listing page. When it is wrong, every new size adds another row, and the range slows itself down as it widens.

A specific record model does not force a specific stack. The size of this catalogue never called for a separate search or cache layer; the store runs on Laravel and MySQL. Two decisions that usually get bundled together are in fact independent of each other: one follows from the unit the business sells, the other from scale. In our e-commerce work the first thing we write down is therefore not a screen. It is what the sellable unit is.

The test has a limit. This model works where price comes off a single axis. Bottle size sets the price on its own and no other choice interferes with it. Once two choices set a price together, a single-axis variant model runs out, and the boundary has to be drawn somewhere else entirely.

When two axes meet, the record is the combination

In the car trade what is sold is not an item on a shelf. It is the outcome of a configuration. The buyer assembles the car first: which trim package, which colour. In the KGM SsangYong online sales channel, where the trim-and-colour pairing is a record in its own right, the variety does not live on one axis. It lives in the product of two.

The contrast with perfume is exact. A bottle size was a sufficient distinction on its own — know the size and you know the price. With a car, knowing the trim is not enough and knowing the colour is not enough. What sets the price is the value the two take together. So the price is written neither on a trim record nor on a colour record, but on the record that stands for the pairing, and every trim-and-colour pairing sits in the catalogue with a record of its own.

The alternative would have been to hang the price on one axis and treat the other as a surcharge: the price of the trim, plus a difference for the colour. On paper that is the economical arrangement, because it asks for fewer records. The bill arrives the moment pairings can be priced independently of each other. If one colour costs nothing extra on one trim and something on another, the addition rule breaks, and it grows a new branch at every exception. Held at pairing level, there are no exceptions left to hold: each pairing carries its own value in its own record.

This is also the line off-the-shelf cart software cannot cross. Those products tie price to a single product record and cannot express a trim-and-colour split. A settings screen will hand over a variant field, but it will not tell you whether that field can hold a price and a set of sales terms. Building the record at pairing level is what made this part of the channel bespoke.

For the visitor the effect is quiet. Change the trim or the colour and the price and the car on screen update at the same moment. They agree with each other because both are read out of the same pairing record. Kept in two separate places, agreement would rest on a matching rule, and that rule would be one more object to verify every time a pairing was added.

A variant record holds more than a price

The word variant is usually read as a price difference. At record level that reading turns out to be narrow. Which fields a variant record holds changes from catalogue to catalogue, and the list does not come down from a template.

In the SsangYong channel the pairing record holds three things at once. The first is the price. The second is the image: every trim-and-colour pairing has its own picture of the car, and the picture is kept at pairing level rather than at model level. Change the colour and the car on screen changes, because the image is attached where the choice was made. Had the image stayed on the model record, a visitor could pick one colour and look at a car in another, and what the screen shows would drift away from what the price says.

The third is the sales terms. Each pairing goes into the catalogue with terms of its own. Had the terms been attached anywhere higher, two different configurations would have been forced to share one set of them, and an arrangement that applied to one trim would have appeared on a trim where it did not apply at all. Holding terms at pairing level also means that on the day the terms change, there is exactly one record to touch.

Putting the two catalogues side by side shows that the field list is not fixed. In perfume the sellable unit holds price and stock, while the image stays at fragrance level, because a bottle size does not change what the product looks like. In the car channel the pairing record holds price, image and sales terms together. One word is naming two different record shapes.

The rule underneath is short. The field list of a variant record comes from a question. Whatever the buyer’s choice changes belongs at variant level; whatever stays the same across choices belongs on the umbrella. Catalogues that skip this sorting end up with fields on the wrong layer, and correcting the layer later means touching every record written in the meantime.

A browsing axis is not a variant

Not every distinction in a catalogue is a variant. Some distinctions do not divide the product at all; they open a second route towards it. Telling the two apart takes the same question again.

In Kokudankokuya a second axis stands beside the category tree: fragrance family and note. This is where a customer who does not know the brands begins. What they are after is not a name but a character, and the axis exists as the answer to that intent.

How it differs from a variant is in the shape of the link. Under a variant, a unit belongs to exactly one umbrella: a bottle size is a size of one fragrance and nothing else. A note is many-ended. One perfume can link to several notes, and the same product becomes reachable from several different searches instead of being locked into one branch of the tree.

The deciding test is still price and stock. No price hangs on a note or on a fragrance family, and no stock does either. Nobody buys a fragrance family; they buy a specific bottle of a specific scent. The sellable unit stays the bottle size, and the note stays a route.

Both kinds of distinction live in the same catalogue without conflict: size is a variant, note is a relation. Building either one with the other’s mechanism does damage in both directions. Model a note as a variant and every note gets a stock counter that will never hold a meaningful number. Model a size as a relation and the price is left with nowhere to sit.

Which kind a distinction is does not always announce itself at the start. A property that behaves like a browsing axis turns into a variant on the day the business starts pricing it separately. There is one signal for that change: if a separate price or a separate stock figure is being kept for the property, it has stopped being a link. In this catalogue the boundary has held, because a note remains a way of searching and needs no counter of its own.

Before deciding where a distinction belongs, check whether price and stock hang on it. If they do, it is a sub-record. If they do not, it is a link.

When every unit is unique, there is no variant model

Both examples so far were catalogues that sell many copies of the same thing. Some catalogues have no such condition to work with.

On the Plastik ve Makina platform, where every machine is published on its own, the unit of record is not a product but a listing. New and second-hand plastics processing machines are listed in the same place, and the listings are not modelled as versions of one another. There is no shared product record to build variants on top of, because no two used machines are the same object: age, hours and condition differ in each one.

The difference in price and stock follows from that. The platform does not broker the sale; negotiation and payment stay between the parties. Price and stock therefore never attach to the system as an operational load the way they do in a shop. And since the quantity of a listing is settled by the listing itself, a stock counter would answer no question that anyone is asking.

So what is the distinction between new and second-hand? A filter axis, not a variant. Both states sit in one list, and the buyer opens the filter to compare them inside a single search. In separate lists no comparison would be possible: a buyer could not see the price of a used machine next to a new one. Where a distinction is placed bears directly on the decision the buyer is trying to make.

The whole category tree is built on the distinctions of one machine family. What would be a sub-line under an industrial heading on a general classifieds site is the main axis here. Laravel builds the list on the server and Inertia hands it to the browser, so changing a filter does not reload the page.

Imposing a variant model on this catalogue would produce an empty hierarchy: one unit beneath every umbrella. The record would gain a layer and answer nothing with it. The distinction also marks what separates a shop from a classifieds platform. A shop sells the same product over and over; a platform publishes each record once. In the first, stock is a counter; in the second, it is a condition.

Where each distinction goes: four approaches side by side

There is a fourth case, and it completes the picture. In the Çatalca Merkez Kasap QR menu, published as a single page, the price sits directly on the menu line. There is no variant, because nothing beneath the line is priced separately. No ordering, payment or stock layer was ever built, so the stock question never comes up. The menu is divided into sections and every section has an address of its own; different QR codes land on different points of the same page. Content that lives as a single record with no variants usually belongs on the content management side.

Set the four approaches beside one another and what separates them turns out to be a question.

ApproachWhat the record stands forWhere price and stock attachHow the variety opens to the buyer
Single record, no variantsA menu line — one row on a QR menu pagePrice sits on the line itself; no ordering, payment or stock layer was ever builtThe menu is split into sections, each with its own address; different QR codes land on different points of one page
Variant on one axis (bottle size)The fragrance is an umbrella record and each bottle size beneath it is a sellable unitPrice and stock are written on the size; the fragrance record carries neitherFragrance family and note beside the category tree; one perfume links to several notes
Record at combination level (two axes)Each pairing of trim and colour is a record in its own rightPrice is written on the pairing, and so are the image and the sales termsA configurator: as trim and colour are chosen, price and the car on screen move together
One-of-a-kind listing (no variants)Each listing is a record on its own; listings are not versions of each otherNegotiation and payment stay between the parties; the system runs no price-and-stock operationA category tree built on one machine family; new versus used is a filter over one list

The second column answers the first, and the third column follows from both. Once it is settled what the record stands for, where price and stock get written follows on its own, and how the variety opens to the buyer comes after that. Reverse the order and the screen gets drawn first, after which the record is bent to feed it.

The four rows are not a ladder. The QR menu is not an incomplete catalogue on its way towards a combination-level record; it is a complete answer to its own question. In the same way, the classifieds platform is not a shop that has yet to reach a variant model. Each row corresponds to a different answer about price and stock.

There is one way to read the table against your own catalogue: finish a sentence. “In our business, price and stock sit on ___.” Whatever fills the blank is the sellable unit, and the variant boundary runs exactly there. If two choice axes have to go into the blank at once, your answer is the third row. If nothing goes in it at all — the price is settled in negotiation and there is no stock to keep — your answer is the fourth row, and what you are building is a list of listings rather than a catalogue.

Key takeaways

  • Draw the variant boundary by asking which record price and stock attach to, before building the catalogue.
  • Keep the product record as an umbrella and let the sellable unit beneath it carry price and stock.
  • When two option axes set the price together, model the record at the level of their combination.
  • An axis without price or stock is a relation for browsing, not a variant — model it as a link, not a sub-record.
  • When every unit is unique, publish listings with filter axes instead of building a variant model.

Questions this article answers

  • Are two sizes of the same product two products, or one product with two variants?

    Let price and stock decide, not the size itself. If each size sells at its own price with its own stock, both belong under one product record as separate sellable units. That is how bottle sizes work in the Kokudankokuya perfume store: the fragrance appears once in the catalogue, and each size keeps its own price and stock. Opening a product per size bloats the catalogue; collapsing everything into one record loses per-size tracking.

  • Does price and stock go on the product record or the variant record?

    On the sellable unit, not the product. In Kokudankokuya, a fragrance is an umbrella record that holds no price and no stock; both live on the record for each bottle size beneath it. The growth test makes the difference visible: adding a new size means adding a unit under the existing umbrella, not opening a new product.

  • When colour and trim combine, which record does the price attach to?

    To the record that represents the combination itself. In the SsangYong online store, what is sold is a configuration outcome: trim package and colour set the price together, so the price is written on their pairing rather than on either axis alone. Off-the-shelf cart software ties price to a single product record and cannot express this split. When the buyer changes a selection, price and image update together because both are read from the same pairing record.

  • Are browsing axes like fragrance family or note variants too?

    No. An axis that carries no price and no stock is a relation, not a variant. In Kokudankokuya, fragrance family and note open a second way to browse beside the category tree, so a customer who does not know a brand can start from a scent's character. One perfume can link to several notes, yet the sellable unit stays the bottle size. Two kinds of distinction sit in the same catalogue: size is a variant, note is a relation.

  • If every unit is unique — like second-hand machinery — do I still need variants?

    No. When no two units are alike, the record is a listing, not a variant. On Plastik ve Makina, every machine is published as its own listing; the platform does not broker the sale, negotiation and payment stay between the parties, so price and stock never become an operational load in the system. New versus used is a filter axis rather than a variant: both states sit in one list and buyers compare them in a single search.

About the author

Algoriel

Remote web software agency

We build custom web and mobile software for businesses. Here we answer the questions that come up while your software is being built and after it goes live.

Tags:
  • product variants
  • catalogue data model
  • sellable unit
  • ecommerce data modelling
  • variant management

Have a system to build?

If there is a system you want built, the quote form is the place to describe it.