Migration log · entry 006 · August 2026

Best price wins.

Our pricing makes one promise: the customer always gets the lowest price we’ve ever agreed to give them. This entry is about the machinery behind that promise — and why it became the migration’s clearest case for building custom.

Behind the promise is machinery. The legacy ERP prices every line through eight tiers of rules — a price negotiated for this customer on this exact item, a discount for this customer across a category, deals by customer type, volume pricing on the item itself, blanket category pricing — each rule carrying up to ten quantity breaks and one of three price bases: a flat price, a discount off list, or a markup on cost. Rules have start and end dates, so contracts and promotions expire on their own.

And here’s the part that surprises people: the tiers aren’t a hierarchy. Every matching rule is evaluated, every time, and the lowest computed price wins — even if that means a general category rule beats a price we negotiated with that customer personally. The promise is absolute.

The pricing engine: every matching rule across eight tiers is evaluated and the lowest computed price wins One item, one customer, one quantity the question: what’s the price? Every matching rule is evaluated — all eight tiers, every time tier 1 Customer + item tier 2 Customer + category tier 3 Customer type + item tier 4 Customer type + category tier 5 Customer only tier 6 † Item only tier 7 Customer type only tier 8 † Category only † no customer dimension — public pricing; guests see these two tiers too Lowest computed price wins that’s what the customer pays Each rule: up to ten quantity breaks · flat, discount-off-list, or markup-on-cost · date-bounded
Eight tiers in, one price out — the cheapest one, always.

That promise had to survive the migration intact. Our standing rule is to use the platform’s built-in machinery first and to the fullest — and we tried. But the built-in pricing model and ours are fundamentally different shapes: the platform wants one pricelist per customer, evaluated by specificity. Ours wants everything evaluated at once with the cheapest answer winning. Forcing one shape into the other would have meant custom code that also fights the framework — the worst of both worlds. So pricing became a custom engine: our eight tiers, our breaks, our bases, replicated exactly. And there’s a long-game payoff — when the legacy system finally retires, the pricing engine doesn’t need a second migration. It’s already home.

The rules came across cleanly: 1,167 imported, thirty skipped because they pointed at products that no longer exist, zero errors. One decision made the store friendlier along the way: two of the eight tiers have no customer dimension at all — pricing on the item itself, pricing on the category. Those are effectively public prices, so guests now see real volume pricing before they ever log in.

The bigger lesson came after the engine worked: pricing isn’t a display feature, it’s infrastructure. Early on the engine answered in only a couple of places while the rest of the platform quietly read its own default prices. The fix became a standard — one engine, one endpoint, and every surface that shows a number calls it. No page computes its own price. Ever.

Data in, data improved, data findable — and now, priced like we promised.