A parcel weighs two kilograms. Its dimensions make its volumetric weight 4.8 kilograms. One service prices the larger measurement, rounded up to a whole kilogram; another prices actual weight. The same parcel gives those services pricing weights of five and two kilograms.
Calculating a weight once and sharing it across both candidates would save work. It would also calculate the wrong thing. The reusable fact is the parcel’s geometry, not whichever service’s policy happened to run first.
This distinction ran through the rating engine’s preparation code. Some facts belonged to the request, some came from converting physical measurements, and some only existed after a candidate’s policies were applied. They eventually fed the same tariff matcher, but that didn’t make them interchangeable. To understand which row matched, we need to follow how its input became a number.
Tables replaced pricing expressions, not every computed fact
The formula-to-table redesign removed the old expression-driven pricing path. It didn’t remove the separate computed-property system. A table still needed facts to test: whether a route was domestic, how many legs a shipment had, or a value derived from earlier facts. Writing those facts into every tariff row would have moved the duplication rather than removed it.
The request-level pipeline first resolved an active computed-formula set for the division, operation and decision instant. It checked required property coverage and whether the set needed explicit shipment legs. Only then did it execute the formulas and return their values, the set’s identity and per-value provenance. Missing coverage and missing required legs were failures, not instructions to continue with a partly populated set.
The stored graph had an execution order. The database read model selected
formula records with orderBy('formula.sequence'); the executor consumed the
resulting list. Consider these two expression fragments, with identity,
language and metadata fields left out:
[
{
"property_path": "totals.leg_count",
"formula_expression": {"count": {"var": "legs"}}
},
{
"property_path": "route.is_multileg",
"formula_expression": {
"greaterThan": [
{"var": "totals.leg_count"},
{"const": 1}
]
}
}
]The executor mirrored shipment.legs into a top-level legs namespace. With
two legs, the first expression produced two; the second read that newly
derived value and produced true. This wasn’t a collection of independent
expressions which could be evaluated in any order or spread across workers.
Each successful step changed the context the next step received.
The following is the success path from the actual executor. Definition decoding, language validation, provenance construction and the failure branch are omitted so the read/write dependency stays visible:
foreach ($formulaSet->formulas as $formula) {
// Resolve $propertyPath, $expression and $formulaMetadata.
$result = $this->formulaEvaluator->evaluate(
$expression,
$evaluationContext,
);
// Failed results are handled before this success path.
$computedPropertyValues[$propertyPath] =
$this->computedValueNormalizer->normalize(
$result->value,
$formulaMetadata,
);
$this->payloadAccessor->setValueAtPath(
$evaluationContext,
$this->payloadAccessor->segmentsForPath($propertyPath),
$result->value,
);
}The returned value map was sorted by property path afterward. That made its output ordering stable; it didn’t reorder execution or repair an earlier missing dependency. Moving the second expression before the first in a direct executor call demonstrates the difference. With its explicit missing-dependency fallback enabled, the flag becomes null, the count becomes two later, and the flag is not rerun. Without that permission, execution fails.
These direct executor calls bypass publication and the pipeline’s coverage and leg guards. They expose the supplied-order assumption, not an admitted misordered set. A caller can’t treat the final sorted map as evidence that evaluation was independent of order.
A value envelope didn’t convert its units
Computed values had an envelope containing value, value_type and optional
unit or currency metadata. The normalizer’s job was to produce that shape.
It wasn’t a general conversion or coercion layer. Its ordinary path began
like this:
$valueType = $formulaMetadata->valueType();
$normalized = [
'value' => $value,
'value_type' => $valueType instanceof ComputedFormulaValueType
? $valueType->value
: $this->inferValueType($value),
];
if ($formulaMetadata->unit() instanceof ComputedFormulaUnit) {
$normalized['unit'] = $formulaMetadata->unit()->value;
}A numeric string such as "12.50" remained a string even when the metadata
said decimal. A value of 2,000 with metadata saying kilograms remained 2,000.
Adding a unit label didn’t establish that the expression had calculated that
unit correctly. These are the normalizer’s direct outputs, not claims that
every such annotation would pass formula publication or request admission.
Null had its own early return: {"value": null, "value_type": "null"}. Unit
and currency annotations weren’t added to it. Null could be a successful
expression result or an allowed dependency fallback; the executor didn’t turn
every evaluation error into null. The fallback policy accepted a
missing-variable error when enabled, and certain operand/collection errors
when a declared dependency didn’t resolve to a non-null value. Other failures
still failed the formula set.
Later, the candidate context assembler unwrapped each computed envelope’s
value into its property path. An envelope without that key raised an
exception. This gave the matcher ordinary values to read, but it didn’t turn
an annotation into a measurement. The expression, its input assumptions and
the conversion path still had to agree.
Physical measurements had a separate conversion path
Package geometry used an explicit unit converter. Weight was normalized to kilograms and dimensions to centimetres. For the running parcel, the physical input could use different supported units without requiring the pricing policy to know which ones the caller had chosen:
{
"id": "parcel-A",
"weight": {"value": 2000, "unit": "g"},
"dimensions": {
"length": {"value": 400, "unit": "mm"},
"width": {"value": 0.3, "unit": "m"},
"height": {"value": 20, "unit": "cm"}
}
}This is a package fragment, not the complete request. Its geometry resolves to two kilograms and 40 × 30 × 20 centimetres. The actual scalar weight conversion made the convention explicit:
return match ($unit) {
'kg' => $value,
'g' => $value / 1_000.0,
'lb' => $value * 0.453_592_37,
'oz' => $value * 0.028_349_523_125,
default => null,
};Unsupported units returned null rather than guessing. Missing measurements also remained meaningful: incomplete dimensions couldn’t produce a volumetric weight. The ordinary package rules allowed missing measurements, as the explicit-parcel chapter shows. An identifiable parcel wasn’t automatically a fully measured parcel.
These calculations used floating-point values. Decimal amount columns in the pricing schema didn’t make every measurement calculation decimal arithmetic. The conversion constants, comparison boundaries and rounding positions were part of the implementation to preserve and test, not details made irrelevant by the money type used elsewhere.
The candidate’s policy selected the pricing weight
Geometry alone still wasn’t a chargeable weight. The context assembler added the candidate’s resolved service before normalizing packages and calculating metrics. The weight-policy coordinator could therefore check a policy’s service match and criteria against that context. A policy rejected at that boundary fell back to the physical weight; its rounding wasn’t applied anyway.
Within an applicable chargeable-weight policy, row overrides had another specific rule: take the first row satisfying both candidate and criteria callbacks. Declaration order mattered. This was not “apply every matching override” or “sort all matches and choose the highest priority.”
The resolver overlaid selected non-null fields from that first row onto the base policy. A null row field inherited the base value. Zero was retained, not discarded by a truthiness filter. That distinction mattered for values such as a rounding increment, because a non-positive increment caused the calculator to leave the weight unrounded.
For the parcel above, a divisor of 5,000 cubic centimetres per kilogram gave 24,000 / 5,000 = 4.8 kilograms. The calculator first converted the package’s cubic-centimetre volume into the divisor’s configured volume unit, divided, then normalized the resulting weight into kilograms. The volume and weight units on the divisor were both part of the calculation.
Selection itself was straightforward:
$chargeableWeightCanonical = match ($selectionStrategy) {
'actual_only' => $weightCanonical,
'volumetric_only' => $volumetricWeightCanonical,
default => match (true) {
$weightCanonical === null => $volumetricWeightCanonical,
$volumetricWeightCanonical === null => $weightCanonical,
default => max($weightCanonical, $volumetricWeightCanonical),
},
};Under the maximum strategy, missing dimensions could leave the actual weight
usable. Under volumetric_only, the same missing dimensions meant no selected
weight. A completely absent policy returned actual weight unchanged. Those
aren’t equivalent fallback decisions, even if a well-measured happy-path
parcel makes them look interchangeable.
Rounding came after selection. The increment was itself converted to kilograms, then the calculator divided by that increment and applied ceil, floor or round before multiplying back. A 1,000-gram increment therefore acted as one kilogram, not 1,000 kilograms.
| Policy | Selected → rounded (kg) |
|---|---|
| Maximum, ceil to 1 kg | 4.8 → 5 |
| Actual only, ceil to 1 kg | 2 → 2 |
| Volumetric only, floor to 1 kg | 4.8 → 4 |
These are synthetic policies executed through the source helpers, not a carrier’s tariff or a benchmark. They demonstrate why the candidate mattered. Reversing two otherwise matching policy rows could change which strategy applied without changing the parcel at all.
Rounding a shipment was a different calculation
The package-metric helper resolved geometry, chargeable weight and freight weight for one package. The shipment helper passed that operation into the aggregator, then separately resolved the shipment-level freight policy. It didn’t total physical weight first and call that a substitute for the package calculations.
Here is the relevant aggregation call, with the optional geometry-index argument omitted:
$aggregate = $this->shipmentMetricAggregator->aggregate(
$packages,
fn (array $package): array => $this->packageMetrics(
$package,
$pricingChargeableWeightPolicy,
$pricingFreightWeightPolicy,
$context,
$rowMatchesCandidate,
$rowMatchesCriteria,
),
);Two 490-gram parcels make the difference obvious. With actual-weight pricing and a one-kilogram ceiling per package, each contributes one chargeable kilogram. The actual shipment helper returns 0.98 kilograms of physical weight and two kilograms of chargeable weight. Adding physical weight and rounding once would give one chargeable kilogram instead.
Neither arithmetic rule is universally right. A tariff can deliberately price the shipment total. But replacing package rounding with shipment rounding changes the rule; it isn’t an optimization of the same calculation. A tariff condition capped at one chargeable kilogram could now match different input, before we even get to applying its amount.
Freight weight remained another policy boundary. In the no-freight-policy path, the resolver preferred the available package freight total, then chargeable weight, then actual weight. The two-parcel example therefore also returned two kilograms there. That fallback doesn’t describe every configured freight policy, which could choose and round a different source metric.
Reuse geometry without reusing a service’s answer
There was still work worth sharing. The geometry index stored normalized physical metrics by package ID along with the raw weight and dimensions used to derive them. Lookup checked those raw inputs before returning the cached geometry:
if (
($package['weight'] ?? null) !== $entry['weight']
|| ($package['dimensions'] ?? null) !== $entry['dimensions']
) {
return null;
}
return $entry['geometry'];A changed measurement refused reuse, and the caller resolved geometry again.
The index didn’t contain chargeable-weight policies or their results.
packageMetrics() could reuse the same physical geometry while applying
another candidate’s weight policy afterward. This was a narrower reusable
boundary than “all metrics for package A.”
The distinction also kept a useful alternative available. If a genuinely shared policy and all its matching context were fixed, some derived work could be reusable too. That would need an identity covering those inputs, not just the parcel ID. Nothing in a faster lookup makes two service policies equivalent.
The useful shared value was the physical geometry; the policy-dependent calculation stayed inside the candidate’s evaluation. That let the matcher receive the weight this tariff meant, not the first number another service happened to calculate for the same box.