Skip to content

Cost to Serve

Work out the true cost of serving each customer by tracing the costs your scenario already recorded back through the network to the demand points that drove them.

When to use this

  • You want to know which customers are most expensive to serve
  • You need costs broken down by type — supply, transport, inventory, handling, production
  • You're looking for places to reduce logistics cost

What you need

Three things are refusals — without any one of them the run stops and says which:

  • Demand. A row on demand policy or demand state; either makes a demand point
  • Arcs. The lanes table defines them; where there are no lanes, the flows rows do
  • A product, on your links, demand or supply records

Realized cost on the state tables is not one of them. A scenario with none of it runs and returns no rows, which is the honest answer and not an error.

It reads state, and no policy at all

Every cost it allocates is a realized total already recorded on the scenario. No policy table is consulted and no per-unit rate enters the arithmetic — the rates on supply policy, lanes, handling policy and inventory policy are what the optimizer reads, and populating the state tables from them is upstream work, done by the run that built the baseline.

Cost type The number it reads
Transport Transport Cost on the flows table — the realized total for that flow, carried onto the lane it matches. A lane with no flow on it contributes nothing
Supply Realized Supply Cost on supply state
Inventory carrying Realized Carrying Cost on inventory state
Handling Realized Handling Cost on handling state
Production Realized Cost on production state, plus the components' rolled-up cost, injected at the producing location

How it apportions. Each location's recorded cost is pushed forward to the demand points its outbound flows reach, split in proportion to those flows — a linear system solved once per product, so a cost at a hub reaches every customer the hub serves in the ratio the hub actually shipped in. An absent state row contributes zero. Nothing is cross-checked against anything: the output is the allocation, not a reconciliation.

Products are processed component-before-output, so a finished good's cost to serve carries the cost of the components its recipe consumed.

What you get

A per-customer cost breakdown: for each demand point and product, one row per cost type with a non-zero amount, as a result table on the scenario. Wire it into Save Data to export, into a dashboard to chart it, or into another analysis to keep going — downstream nodes still see the full scenario plus the new breakdown. Results are saved with the scenario when the node runs in a workflow.

Workflow wiring

This node takes scenario data — wire it after Create Scenario, Load Scenario, or another analysis step. Do not wire it straight to a Map node.

flowchart LR
    n1["Import Data (locations.csv)"] --> n2["Map Locations"]
    n3["Import Data (shipments.csv)"] --> n4["Map Transport"]
    n4 --> n5["Create Scenario"]
    n5 --> n6["Cost to Serve"]
    n7["Import Data (demand.csv)"] --> n8["Map Demand Policy"]
    n9["Import Data (supply.csv)"] --> n10["Map Supply State"]
    n11["Import Data (inventory.csv)"] --> n12["Map Inventory State"]
    n2 --> n5
    n8 --> n5
    n10 --> n5
    n12 --> n5

The state nodes are the ones to wire. Their policy halves belong on the scenario for other reasons — the optimizer needs them — but this node will not look at them.

Common mistakes

  • Wiring this node to a Map node instead of through Create Scenario
  • Mapping only the policy halves and expecting an allocation. Rates are not costs here; with the state tables empty every allocation is zero and the node returns no rows
  • Missing product information on transport and demand records — no product dimension is one of the three refusals