Pricing a product that changes price every morning
- Next.js
- E-Commerce
- Caching

Most e-commerce catalogues store a price. Jewellery cannot: the metal rate moves every day, so a stored price is wrong by the next morning and catastrophically wrong by next month.
What you store instead is everything the price is computed from — and the price becomes a derived value, like a total on an invoice.
Store the inputs, derive the number
A piece is not "₹1,53,989". It is 3.1 grams of 18K, plus a making charge, plus stones, plus GST. Model it that way:
{
netWeightGrams: 3.1,
purity: "18K",
makingChargeType: "percent", // or "per_gram" / "flat"
makingChargeValue: 12,
stones: [{ type: "diamond", carat: 0.5, ratePerCarat: 68000 }],
}The price function takes this plus today's rate for that purity and returns both a total and the line items that produced it. Write it once, server-side, and let every surface — listing, product page, cart, invoice — call the same function. The moment two code paths compute price independently, they will disagree, and the one that disagrees on the invoice is the expensive one.
Show the breakup, because it is the whole pitch
Having built the calculation as line items, the highest-value thing you can do is show them. Metal weight, today's rate, making charge, stone value, GST.
This is not a transparency gesture, it is conversion work. The reason high-value jewellery stalls at the product page is that the buyer cannot tell what they are paying for. A breakup answers the objection at the exact moment it forms, and it is only cheap to render because the pricing function already returns the parts.
Cache the rate, not the page
The instinct is to make product pages dynamic so prices stay fresh. That throws away static rendering for the entire catalogue to track a number that changes once a day.
Invert it. The rate is one small, slow-moving value:
Fetch and store it on a schedule, with the fetch timestamp.
Render pages statically against the current rate.
Revalidate on rate change rather than on a timer, so pages rebuild when the number actually moves.
If your rate provider fails, serve the last known rate and its timestamp — visibly. A slightly stale rate labelled "as of 9:15am" is a normal shopping experience. A page that 500s because a third-party feed timed out is not.
Pin the rate at checkout
The one place freshness genuinely matters: the moment money is committed.
When an order is placed, snapshot the rate and the full computed breakup onto the order document. Never recompute a historical order from the current rate — a customer opening last month's invoice must see last month's numbers, and an accountant reconciling it needs the figure that was actually charged.
Live pricing for browsing, frozen pricing for orders. Getting that boundary right is most of the work.
The edge case that will find you
Decide what happens to a cart when the rate changes between adding and paying. Silently repricing at checkout is the worst option — the customer sees a total they did not agree to and abandons.
Hold the quoted price for a defined window, show when it expires, and re-quote explicitly when it does. It costs a little margin on volatile days and it buys a checkout the customer trusts.