DEV Community

Qtim
Qtim

Posted on

A marketplace pricing engine should not rewrite yesterday’s order

A commission rule can change in a minute. Reproducing a calculation from last month is harder once the new rate has replaced the old one in a shared reference table.

An operations manager opens a disputed order. The commission total is there, but the rule changed yesterday. The seller is asking why the payout looks this way, and the product team has to decide whether a recalculation is safe.

About this article. At Qtim, complex e-commerce products are designed and developed. This is a practical architecture note, not a description of a ready-made tariff product or a client result.

A pricing engine stops being a percentage field when a team must explain a past amount. It becomes a system that connects order facts, a version of a rule, the rule’s effective moment, and an explanation of the result.

A result needs more than the current rate

Commission, discount, shipping, and partner payout can be separate calculations. Their results still need a shared record of how a decision was made. Otherwise a later rule change turns historical orders into totals that must be reconstructed from logs.

The practical instrument is a calculation passport:

This is a domain boundary, not a mandatory technology choice. The data that determines an amount needs to stay distinguishable from data introduced later.

PostgreSQL documents range types and illustrates one implementation option: represent a period explicitly and prevent overlapping ranges for the same key. A marketplace may choose another implementation, but it still needs an explicit answer for conflicting active rules.

Map the entities and events in an e-commerce calculation with Qtim before implementation starts. The first useful output is a shared description of which event selects a rule, which facts are frozen, and who can change a published version.

What should become immutable

Immutability does not mean a product can never correct data. It means a completed result keeps enough evidence to distinguish an original decision from a later correction. A team can add a rule version, a compensating financial adjustment, or a recalculation run. It should not silently replace the historical explanation.

That distinction protects three conversations. Support needs to explain one order. Finance needs to reconcile a population of orders. Product needs to change a future rule without guessing which historical objects will move with it. The same calculation passport serves all three, but each role reads a different part of it.

The cost of omitting a trace is operational. A support specialist receives a total without the selection reason. An engineer sees a rate but not the conditions that admitted it. A product manager sees a new rule and cannot tell whether it should trigger a financial correction. A compact chain of inputs and choices gives those roles one object to inspect.

Publishing a rule deserves its own workflow

Use a synthetic example. A category commission changes from 12% to 13% on November 1. An editor creates a draft, sets its effective period, validates it, and publishes a new immutable version. The old version remains available for historical calculations.

Before publication, the product needs four checks:

  1. Required inputs are present: scope, rate, currency, conditions, and effective date.
  2. The same key has no unresolved period overlap.
  3. Control examples return the expected amounts.
  4. The publication has an audit record: who approved it, when it became active, and why. It also helps to separate effective_at from recorded_at. The first is the business moment when a rule applies. The second is when the system learned about the rule. A retroactive change needs an explicit policy; otherwise a recalculation can expand its scope without anyone choosing that outcome.

A publication workflow makes ownership visible

The workflow makes ownership visible. A person or role proposes a change, another role validates examples and overlap rules, and a publication event makes the version eligible for calculation. Small teams can combine these responsibilities. The system should still record which decision happened and when.

This matters when a rule contains more than one percentage. A category rate may coexist with a seller exception, a regional condition, or a delivery threshold. The article does not assume every marketplace uses this model. It requires the team to state which dimensions form a rule key and which priority resolves a conflict.

Preview calculates; a posting creates an effect

A preview should use the same input facts and rule version as a final calculation, yet return only the amount and its trace. That separation lets a team test a proposed change before it creates a financial record.

Build golden cases around the edges of the domain:

Katalon reports responses from more than 1,500 QA professionals and focuses on automation and quality. It does not prescribe a pricing-engine architecture. Its useful prompt here is narrower: interface-level formula checks do not cover rule selection, effective-date boundaries, or the consequences of a repeated run.

A trace gives both support and development a short chain to inspect: input amount → applicable rule → rate → rounding → final total. That makes a disputed total testable rather than merely explainable.

Golden cases are a shared contract

The table keeps business and engineering from testing different things. A product manager can approve the expected outcome at a period boundary. An engineer can implement the selection order. QA can turn the same row into an automated assertion. Support can later compare a disputed order with the case that describes its class.

Golden cases also make changes reviewable. When a new version alters an expected output, the team has to decide whether the altered output is intended. A passing deployment then means more than a service responding successfully: the visible examples still match the approved rule.

Bulk recalculation is a bounded job

Teams reach for recalculation when they decide to change past results, repair source data, or simulate a new scenario without an immediate financial effect. These are different modes and should not share an unnamed “recalculate everything” button.

Each job should fix its population snapshot, reason, target rule version, mode, run ID, batch IDs, progress counters, and reconciliation result. Batches limit the blast radius: a system processes a predictable group of identifiers, records its status, and then proceeds.

The batch size is not a universal number. It depends on calculation time, locking, external-system limits, and rollback requirements.

Repeating the same run should not silently create a second financial effect. A practical design is to model the identity of a run, batch, and result separately from the formula. This is a design recommendation, not a claim that every marketplace must implement it in one way.

In our Yurkas case, an online store for doors and materials, Qtim developed the product-configurator core through separate domain modules and background queues for mass price recalculation. The same separation matters in a pricing engine: recalculation work should not be confused with selecting a rule version.

Completion needs reconciliation, not only a done status: how many objects entered the snapshot, how many changed, where exceptions occurred, and which records still need human review.

When the full model is more than a product needs

The model has a cost. It creates more identifiers, audit data, and decisions at publication time. A simple catalogue calculation that never affects payments, reports, or disputes may not need the same level of history. The useful boundary is the consequence of being unable to explain a past amount.

Once an amount affects a payout, an invoice, a partner balance, or a customer dispute, the simpler model becomes risky. The extra data is the record that lets a team distinguish a changed rule, a rerun job, and a financial correction.

Four histories must stay separate

  1. A business-rule version: rate, scope, and period.
  2. An algorithm version: code that interprets the rule and builds the trace.
  3. A recalculation run: its population, reason, parameters, and progress.
  4. A financial adjustment: a separate effect on balance or payout. Keeping only the current rate can work while history has no effect on money, reporting, or disputes. Once a past result must be explained or reconciled, the current rate is no longer enough.

Start discovery with one disputed calculation

Ask which event selects a rule version, which inputs become immutable, what resolves a rule conflict, who publishes a version, what preview can show, which objects may be recalculated, and which reconciliation proves the run is correct.

The decision rule is concise: a historical calculation needs reproducible facts and a rule version; a recalculation needs boundaries, an identity, and reconciliation.

This approach does not remove judgment from the product. It makes the judgment visible before an amount becomes difficult to explain. Teams still choose their rule dimensions, periods, approval roles, and correction policy. The engine records those choices in a form that can be tested and reviewed later.

That is the practical goal for a first iteration: one explainable calculation path, one controlled way to change it, and one bounded way to inspect historical differences.

It gives later product changes a stable place to attach without rewriting the orders that came before them.

That stability matters most when a small rule change reaches a large historical population.

It also keeps future experiments from erasing the decisions that created today’s balances and reports.

When a product already has disputed payouts, changing commissions, or recurring exceptions, Qtim can help map the product boundary before implementation starts.

Discuss one pricing scenario with us to define the first iteration’s domain boundary, inputs, and safe change order.

Top comments (0)