Pepulux
Writing

What a moving gold rate does to your data model

A price tag assumes price is a property of the thing. At a jewellery counter it is a property of the moment — and that one sentence rewrites your schema, your invoice and your idea of what a record is.

Lambodharan K SharmaFounder & CEO

18 September 2026 · 8 min read · Lambodharan K Sharma, Founder & CEO

Almost every point-of-sale system ever written begins with the same quiet assumption: that a product has a price. It sits in a column next to the name, you read it when you make a sale, and if it changes you write a new value into the column. Retail software is built on that sentence the way a house is built on a slab.

A jewellery counter breaks it before you have finished your first cup of tea. The gold rate moves during the trading day. The same chain is one price at ten in the morning and another at four in the afternoon, and neither of those is wrong. Price is not a property of the chain. It is a property of the moment in which the chain was sold.

That is not a pricing feature. It is a different data model, and pretending otherwise is how you end up with a system the shop quietly stops using.

The version that seems reasonable and is not

The obvious first attempt is to keep the price column and update it when the rate changes. A job runs, rates come in, prices are rewritten. Everything downstream — the till, the reports, the stock valuation — carries on reading one number, which is comfortable.

It falls apart the first time somebody asks a question about the past. What did we charge for that piece on the fourteenth? The column only knows what the price is now. You can go looking for a rate history and try to reconstruct it, and you will be close, and close is not a thing you can hand an auditor.

It falls apart again mid-sale. A customer is at the counter, the bill is half-written, the rate updates. Now you have two answers to the same question and no rule about which one the customer owes.

Price as a computation, not a value

What we ended up with treats a line on a bill as the result of a small calculation rather than a lookup. The inputs are the ones a jeweller would name if you asked them at the counter:

  • the weight of the piece
  • its purity
  • the rate at the moment the line was created
  • making charges
  • wastage

Store all of them on the line. Not a reference to a rate table that may be edited later — the actual number that was used, copied onto the line at the moment it was used.

This offends a certain kind of engineer, because it is denormalised on purpose and you can hear the objection forming: now the rate lives in two places and they can disagree. They can, and that is the point. An invoice is not a view of current state. It is a record of a decision, and a record that changes when the world changes is not a record.

The moment the rate is stamped

Once price is a computation, you have to decide exactly when it is performed, and that turns out to be a business decision wearing a technical costume.

We settled on the moment the line is added to the bill, not the moment the bill is paid. A customer who has been quoted a figure while the piece is being weighed should not find it has moved while they are getting out their card. If a bill sits open long enough to matter, the shop can refresh it deliberately — but the software will not do it behind anyone’s back, because the counter is a conversation and software should not change what was just said out loud.

Write that rule down somewhere a future developer will find it. It is the kind of decision that looks arbitrary six months later and gets "fixed" by someone who has never stood behind a counter.

Then old gold walks in

Part-exchange is where the model earns its keep or collapses. A customer brings in old gold, it is weighed and assessed for purity, and it comes off the price of the new piece. This is not an edge case. At many counters it is most of the day.

If your bill is a list of positive line items with a total at the bottom, the exchange does not fit anywhere. Teams usually reach for a discount field, and that is the wrong shape — a discount is a decision about margin; an exchange is a valuation of a physical thing that the shop now owns and has to account for. Model it as a discount and your stock is wrong, your books are wrong, and a year later nobody can explain either.

An exchange line carries its own weight, purity and rate, exactly like a sale line, with the sign reversed. The metal enters stock. The value reduces what is owed. Two facts, recorded separately, both true.

What this buys you at audit

Everything above sounds like schema pedantry until an auditor sits down. Then the question is always some version of: explain this number.

With price as a stored value, the honest answer is a shrug and a spreadsheet. With price as a stored computation, the answer is the line itself — this weight, this purity, this rate at this timestamp, these charges, this result. The arithmetic can be redone in front of the person asking. We have watched an audit conversation end early because the answer was simply visible, and that is worth more to a shop owner than any feature you could put on a slide.

This is not really about gold

Any domain where the price depends on the moment has this shape, and most teams meet it eventually: fuel, currency conversion, commodities, energy, anything indexed to a market. The instinct is always to keep one price column and patch around it, because the patch is small and shipping is close.

The rule that has held for us is narrow enough to be useful: if a number could be questioned later, store the inputs and the result together, on the row that used them. Not in a log somewhere. On the row.

It costs a little more to write and it makes the schema less elegant. It also means that in three years, when somebody asks why a customer was charged what they were charged, the software can answer instead of guessing.