Inventory Position Is a State, Not a Number
How to model on-hand, pipeline, commitments, receipts, and timing correctly before optimizing replenishment decisions.
Inventory Position Is a State, Not a Number
A surprising number of replenishment models fail before the optimizer ever sees the problem.
The failure is usually called inventory position.
Someone takes on-hand inventory, adds open purchase orders, subtracts backorders, and produces one number. That number gets passed into a forecast or optimizer as if it completely describes the state of the system.
It does not.
Ten thousand units arriving tomorrow are not economically equivalent to ten thousand units arriving twelve weeks from now. A purchase order that can still be cancelled is not the same thing as a firm shipment on the water. Inventory reserved for a customer is not the same thing as freely available inventory. Stock in a remote node is not necessarily usable at the node where demand occurs.
If those distinctions can change the action, they belong in the state.
This sounds obvious. In production supply chain systems, it is violated constantly.
Start With the Decision
Before defining inventory position, define the decision.
Suppose every Monday we decide how much to order from a supplier for each SKU. Orders must be in case packs. Some vendors have a minimum order quantity. Lead time is uncertain. Existing purchase orders are already scheduled across future weeks. Demand occurs continuously while those orders are traveling.
The actual question is not:
How much inventory do we have?
It is:
Given what we know and what is already committed, what should we order now?
That immediately forces a better representation of state.
At minimum, I usually want to know:
- sellable on-hand inventory by location,
- inventory reserved or otherwise unavailable,
- backorders or unmet commitments,
- open purchase orders by expected arrival date,
- whether each open order is firm, cancellable, or adjustable,
- transfers already in transit,
- expected demand before each receipt,
- supplier and transportation calendars,
- capacity or cash already consumed by prior commitments,
- and the age or vintage of the data used to construct the state.
You may need more. You may need less. The test is simple: could changing this piece of information change today’s decision?
If yes, collapsing it away deserves justification.
A Scalar Inventory Position Hides Time
The textbook inventory position is often written as
[ IP = OH + OO - BO ]
where (OH) is on-hand, (OO) is on-order, and (BO) is backordered demand.
That can be useful bookkeeping. It is not automatically a sufficient state for optimization.
Consider two SKUs with identical values:
- on hand = 100,
- on order = 500,
- backorders = 0.
Both have an inventory position of 600.
For SKU A, all 500 units arrive next week.
For SKU B, the 500 units arrive in sixteen weeks.
If demand is 80 units per week, those are completely different situations. SKU A may need no new order. SKU B may stock out long before its pipeline arrives.
The scalar inventory position destroyed the information needed to distinguish the decisions.
The fix is not a fancier formula. The fix is to preserve the pipeline over time.
Represent the Pipeline Explicitly
Let
[ r_{i,t} ]
be already-committed receipts for item (i) arriving in period (t).
Let
[ x_{i,t} ]
be new order decisions placed in period (t), and let the lead-time mapping determine when those decisions become receipts.
A simple deterministic inventory balance might be
[ I_{i,t+1} = I_{i,t} + r_{i,t+1} + x_{i,t-L_i} - d_{i,t+1}. ]
Even this simple formulation is materially better than passing one inventory-position number into the model because the optimizer can see when supply becomes available.
In a real implementation, the balance may need separate variables for available inventory, backorders, lost sales, transfers, damaged stock, or multiple echelons. The point is not to maximize the number of variables. The point is to preserve the distinctions that affect the decision.
Existing Orders Are Decisions From the Past
Open purchase orders are especially easy to model badly.
They are not merely inventory that has not arrived yet. They are consequences of earlier decisions, and their current flexibility matters.
I like to classify pipeline orders into something like:
- Firm: cannot be changed without violating a real commitment.
- Adjustable: quantity or timing can still be modified, usually at a cost.
- Cancellable: can be removed, perhaps with a cancellation penalty.
- Uncertain: supplier acceptance, production completion, or arrival timing is not guaranteed.
Those categories imply different decision structures.
If an existing order is firm, treat it as state.
If it is cancellable, cancellation may be a decision variable.
If it can be expedited, expedite quantity or mode may be a decision variable.
If its arrival date is uncertain, the receipt belongs in the uncertainty model rather than being hard-coded as a guaranteed deterministic event.
This distinction is important because many systems accidentally count an open PO as both committed supply and available flexibility. The optimizer then believes it has options that operations do not actually have.
Ask These Questions Before Writing the MILP
When I review an ordering model, I want concrete answers to questions like these:
- What exactly is available to satisfy demand right now?
- What inventory is physically present but not economically available?
- Which future receipts are guaranteed?
- Which receipts can still move?
- When does ownership transfer?
- When does capacity get consumed?
- When does cash get committed?
- Are lead times measured from order placement, supplier acceptance, ship date, or receipt date?
- What happens on weekends, holidays, and vendor shutdowns?
- Can receipts arrive partially?
- Can demand be backordered, substituted, or lost?
- Are transfer orders and purchase orders represented consistently?
- Is the same inventory counted at two nodes while in transit?
- What information was actually known when the historical decision was made?
These questions are not data-engineering trivia. They define the optimization problem.
Decision Variables Should Match Executable Actions
Suppose the buyer can place orders in case packs. Let
[ k_i ]
be the case-pack size and
[ z_{i,t} \in \mathbb{Z}_{\ge 0} ]
be the number of cases ordered.
Then
[ x_{i,t} = k_i z_{i,t}. ]
If vendor (v) has a minimum order value (M_v), with unit purchase cost (c_i), we might introduce an order-activation binary (y_{v,t}):
[ \sum_{i \in v} c_i x_{i,t} \ge M_v y_{v,t}. ]
We also need an upper linking constraint so quantities cannot appear when (y_{v,t}=0).
If warehouse receiving capacity is limited,
[ \sum_i a_i q_{i,t} \le C_t, ]
where (q_{i,t}) represents actual receipts and (a_i) converts units into the relevant capacity measure.
Notice what happened: once we represented the pipeline by arrival period, the capacity constraint can finally be applied to the period in which inventory actually hits the building.
With a scalar inventory position, that temporal relationship is invisible.
Lead Time Is Part of State and Uncertainty
Lead time is often treated as a static master-data field: 42 days, 56 days, 84 days.
Reality is usually messier.
Supplier production varies. Port dwell varies. Transportation varies. Customs varies. Appointments vary. Existing orders may already be late, which changes their remaining lead-time distribution.
For scenario (s), let a new order placed at time (t) arrive at
[ A_{i,t}^{s}. ]
Then the simulated receipt in future period (u) depends on whether
[ A_{i,t}^{s}=u. ]
Existing pipeline should be treated similarly when arrival uncertainty remains.
This matters because the economic value of another order depends on the distribution of supply already coming toward you.
A supplier with 1,000 units nominally due next week but a 40% probability of slipping three weeks may justify a very different action from a supplier with a reliable next-week receipt.
The mean expected receipt date does not preserve that asymmetry.
Do Not Double Count Pipeline
One of the most dangerous bugs in replenishment systems is also one of the least glamorous: the same supply enters the model twice.
For example:
- An ERP snapshot says on-hand is 500.
- A receipt of 200 units posted overnight.
- The PO feed still shows the corresponding 200 units as open because the feeds are captured at different times.
- The model sees 500 on-hand plus 200 on-order.
- The real state is only 500 total because the receipt is already inside the on-hand number.
The optimizer solves perfectly.
The data state is wrong by 200 units.
This is why every production decision run should have a clear as-of timestamp and reconciliation logic between inventory, orders, receipts, and shipments.
I would rather run yesterday’s fully reconciled state than combine four supposedly fresh feeds captured at incompatible times.
Freshness without consistency is not accuracy.
State Construction Deserves Tests
Optimization teams often have extensive tests around constraints and almost nothing around the state builder.
That is backwards.
I want invariants such as:
[ \text{prior open quantity}
\text{received} + \text{cancelled} + \text{remaining open quantity} ]
subject to the business’s actual transaction semantics.
I want checks for:
- negative available inventory where it is impossible,
- receipt dates before order dates,
- duplicate purchase-order lines,
- impossible lead times,
- orders marked both closed and open,
- inventory simultaneously counted at origin and destination,
- unexplained jumps in pipeline quantity,
- stale snapshots mixed with fresh transaction feeds,
- and large differences between modeled and operational inventory position.
Do not merely log that the data loaded successfully. Log whether the state makes sense.
Uncertainty Does Not Fix Bad State
A probabilistic forecast cannot rescue an incorrect starting condition.
Neither can Monte Carlo simulation.
If the model begins with 1,500 units of pipeline when only 900 are actually coming, drawing 5,000 beautiful demand scenarios just gives you 5,000 precise evaluations of the wrong problem.
This is an important hierarchy:
- Define the decision.
- Define the state needed for that decision.
- Reconcile the state.
- Represent uncertainty around future transitions.
- Optimize the action.
- Evaluate the resulting policy.
Teams frequently start at step four because probabilistic modeling is more interesting than reconciling purchase orders.
Production economics does not care which part was more interesting.
Evaluate Policies, Not Inventory Snapshots
Suppose you are comparing two state representations:
- Model A: scalar inventory position,
- Model B: time-phased pipeline with uncertain arrivals.
Do not compare them only on whether Model B predicts inventory more accurately.
Run both through the actual replenishment policy.
For historical decision dates:
- reconstruct only the information available at that date,
- build the state using each representation,
- generate the order decision,
- simulate or replay subsequent demand and supply outcomes,
- replan at the normal cadence,
- measure realized economics.
Useful metrics include:
- contribution margin,
- lost-sales cost,
- holding cost,
- expedite cost,
- cancellation cost,
- obsolescence,
- receiving-capacity violations,
- working capital,
- stockout duration,
- order volatility,
- and decision disagreement between the two approaches.
The question is not whether the richer state is theoretically nicer.
The question is whether preserving the information changes decisions enough to pay for the added complexity.
A Practical Failure Example
Imagine an imported SKU with eight weeks of average lead time.
Current state:
- 300 units on hand,
- 400 units scheduled for week 2,
- 600 units scheduled for week 8,
- expected demand around 100 units per week,
- case pack of 100,
- vendor MOQ shared with other SKUs.
A scalar inventory position says:
[ 300 + 400 + 600 = 1{,}300. ]
Thirteen weeks of average demand sounds comfortable.
But the actual time path says something else.
The first 300 units cover roughly weeks 1 through 3. The week-2 receipt helps bridge the middle. The 600 units in week 8 do nothing for a shortage in week 6.
If the week-2 receipt is also uncertain, the risk becomes larger.
Now add the vendor MOQ. Perhaps ordering this SKU alone is unattractive, but placing one additional case while another SKU triggers the vendor minimum has positive marginal value.
None of that logic is represented by the number 1,300.
The state needs time, uncertainty, and coupling because the decision has time, uncertainty, and coupling.
Common Failure Modes
Treating all on-order inventory as equivalent
Arrival timing matters. Preserve it.
Using planned dates as guaranteed dates
A planned receipt is not a physical law. Model reliability where it affects decisions.
Ignoring order flexibility
Firm, cancellable, and adjustable orders are different economic objects.
Mixing timestamps
On-hand from 6 a.m. and open orders from midnight can create phantom inventory. Reconcile the state to an explicit as-of time.
Modeling in-transit inventory twice
Define ownership and location semantics. A unit cannot be simultaneously available at both origin and destination.
Using future information in historical tests
If the planner did not know the actual arrival delay on the decision date, your backtest cannot know it either.
Optimizing a perfect state that operations cannot observe
The production policy acts on observed information, not omniscience. Simulate that information process honestly.
Measuring only service level
A richer state may reduce stockouts by massively increasing inventory. Measure the economics, not one KPI.
What I Would Build in Practice
For a production replenishment system, I would separate the architecture into four layers.
1. Raw event layer. Purchase orders, receipts, shipments, cancellations, inventory adjustments, reservations, transfers, and timestamps remain auditable events.
2. State builder. Convert those events into a decision-time state: available inventory, pipeline by expected arrival, commitments, flexibility, capacities, and other relevant attributes.
3. Decision engine. Given the current state and uncertainty model, produce executable actions such as order quantities, cancellations, transfers, or expedites.
4. Policy evaluator. Replay or simulate the system over time, including future state updates and repeated decisions.
Keep those layers separate enough that you can test them independently.
When a strange order appears, you should be able to answer:
- What state did the optimizer see?
- Which receipts did it believe were coming?
- When did it believe they would arrive?
- Which commitments were fixed?
- What uncertainty did it consider?
- Which constraint or economic term drove the action?
If you cannot answer those questions from logs, debugging will eventually become archaeology.
Log the State That Produced the Decision
For every production run, store enough information to reproduce the decision.
At minimum:
- decision timestamp,
- data as-of timestamps,
- on-hand and available inventory,
- pipeline quantities by arrival period,
- order status and flexibility,
- demand distribution or scenario version,
- lead-time model version,
- decision variables returned,
- major binding constraints,
- objective decomposition,
- solver status and runtime,
- and any repair or override applied after optimization.
The exact fields depend on the system. The principle does not.
A decision without its state is almost impossible to audit.
The Bigger Lesson
Supply chain optimization is often presented as if the hard part begins with the objective function and constraints.
In practice, the harder question often comes earlier:
What state is the decision actually being made from?
Inventory is not just a quantity. It has location, timing, ownership, commitment, availability, and uncertainty. Pipeline supply is not just inventory with a delayed label. It is a collection of past decisions whose future consequences arrive at different times and with different degrees of certainty.
Collapse all of that into one number only when you have demonstrated that the lost information does not materially change the action.
Otherwise, preserve the state.
The optimizer can only make a good decision about the world you describe to it.