DEV Community

life
life

Posted on

Chargeable weight: the pricing bug that is not a bug

If you have ever built a shipping quote engine, you have met chargeable weight. It trips up developers because the weight you bill is not the weight on the scale.

The rule: chargeable weight is the greater of actual weight and volumetric weight.

volumetricWeight = (L x W x H in cm) / divisor

The divisor is usually 5000 (air/express) or 6000 (some economy lanes). A small, honest implementation:

function chargeableWeight({ length, width, height, actualKg, divisor = 5000 }) {
  const volumetricKg = (length * width * height) / divisor;
  return Math.max(actualKg, volumetricKg);
}

// 50x40x30 cm box that actually weighs 8 kg
chargeableWeight({ length: 50, width: 40, height: 30, actualKg: 8, divisor: 5000 });
// -> 12  (volumetric wins)

chargeableWeight({ length: 50, width: 40, height: 30, actualKg: 8, divisor: 6000 });
// -> 10  (same box, cheaper lane)
Enter fullscreen mode Exit fullscreen mode

Two things this gets wrong in production if you are not careful:

  1. Rounding. Carriers round up to the next 0.5 kg or 1 kg. Bill before rounding and you undercharge; round the wrong way and you overquote.

  2. The divisor is per-lane, not global. Hardcoding 5000 silently overcharges every customer who qualifies for a 6000 economy lane. Model the divisor as a property of the lane, not a constant.

The "why am I paying for 12 kg when my box is 8 kg" tickets are almost never bugs. They are volumetric weight. Surface both numbers in the UI so the customer sees actual vs chargeable side by side, and the tickets stop.

Top comments (0)