NEW: The Decision Factory — a novel about decisions under uncertainty. Get it on Amazon
Decision Science · · Adam DeJans Jr.

Decision Latency Is a Model Input

A practical guide to modeling the time between observing the world and executing a decision, and why ignoring that delay can make an otherwise good optimization policy fail in production.

decision-sciencesupply-chainoptimizationinventorysimulationpolicy-designproduction-systems

A lot of optimization models quietly assume something that is almost never true in production:

The moment the model observes the state, the decision happens.

It sees 312 units on hand, a forecast, an open purchase order, and a supplier lead time. It computes an order. The order magically exists.

Real systems do not work like that.

The inventory snapshot may have been cut at midnight. The model runs at 4:00 AM. A planner reviews exceptions at 9:00 AM. The purchase order is approved at 1:00 PM. The supplier receives it that evening. Production does not reserve capacity until the next morning.

Meanwhile, demand keeps happening.

That delay is not just an implementation detail. It changes the decision problem.

If a policy is designed assuming zero decision latency and deployed into a process with 24 or 48 hours of latency, you did not deploy the policy you tested. You deployed a different one.

This shows up everywhere: replenishment, allocation, production scheduling, transportation, labor planning, pricing, and even real-time systems where “latency” may mean seconds instead of days.

The practical lesson is simple:

Model the clock that exists between information and action.

Start with the actual decision timeline

Before writing an objective function, draw the timeline.

Suppose a distributor places replenishment orders every Monday.

A simplistic model might say:

  1. Observe Monday inventory.
  2. Compute the order.
  3. Supplier lead time begins Monday.

But the operating process might actually be:

  1. Sunday 11:59 PM: ERP inventory snapshot closes.
  2. Monday 3:00 AM: forecast and inventory pipeline are assembled.
  3. Monday 5:00 AM: optimization runs.
  4. Monday 8:00 AM: recommendations appear in the planner queue.
  5. Monday 2:00 PM: planner finishes review.
  6. Monday 4:00 PM: approved purchase orders are transmitted.
  7. Tuesday 8:00 AM: supplier accepts the orders.
  8. Tuesday: contractual lead-time clock begins.

The model thought it had a seven-day lead time.

Operationally, it may have something closer to eight or nine days from the information snapshot that generated the decision.

That difference matters most when inventory is tight, demand is volatile, lead times are long, or decisions sit near discrete thresholds such as MOQs, truckloads, setup quantities, or service-level triggers.

Ask these questions before modeling anything

When I am trying to understand a production decision process, I want answers to questions like these:

  • What exact timestamp defines the state used by the model?
  • When is the forecast generated?
  • When does the optimization actually run?
  • Can the recommendation execute automatically, or does a human approve it?
  • How long does approval normally take? What does the tail of that distribution look like?
  • When does the downstream system receive the decision?
  • When does the supplier, warehouse, carrier, or machine treat the decision as committed?
  • Can the decision be changed after submission?
  • What happens on weekends and holidays?
  • If a job fails, when is the next opportunity to act?
  • Does the lead-time definition begin at recommendation, transmission, acceptance, production release, or shipment?

If nobody can answer those questions, the team does not yet understand the decision process well enough to optimize it.

The state has a timestamp

A state vector is not just a collection of values.

It is a collection of values known at a particular time.

For an inventory problem, we might write the observed state at time t as:

[ S_t = (I_t, O_t, B_t, F_t, C_t, V_t) ]

where:

  • I_t = on-hand inventory,
  • O_t = open-order pipeline,
  • B_t = backlog,
  • F_t = forecast or demand distribution,
  • C_t = relevant capacity state,
  • V_t = supplier or vendor state.

The policy maps that state into an action:

[ x_t = \pi(S_t) ]

That notation is useful, but production introduces another variable:

[ \delta_t = \text{time from observing } S_t \text{ to effective execution of } x_t ]

The action does not affect the system at t.

It affects the system at roughly t + δ_t.

During that interval, the world moves.

Demand consumes inventory. Existing orders may arrive. Capacity may disappear. A supplier may change an acknowledgment date. A backlog may grow. Another decision process may consume the same budget or capacity.

So the state that justified the action and the state in which the action becomes effective are not necessarily the same state.

A concrete inventory example

Assume:

  • current on-hand inventory: 100 units,
  • expected daily demand: 20 units,
  • supplier lead time after order acceptance: 5 days,
  • ordering policy: protect expected demand through replenishment arrival plus safety stock.

If the model assumes the order is accepted immediately, expected demand before replenishment is roughly:

[ 5 \times 20 = 100 ]

Now suppose the real process takes two days from state snapshot to supplier acceptance.

The relevant exposure is closer to:

[ (2 + 5) \times 20 = 140 ]

Those extra 40 expected units are not a small technical correction. They can be the difference between staying in stock and spending several days stocked out.

If demand is uncertain, the effect can be larger because the uncertainty accumulated during the delay also matters.

The model does not merely need the mean demand during the latency window. It may need the distribution of demand during that window.

Teams often bury decision latency inside “lead time.” Sometimes that is fine. Sometimes it creates a mess.

I prefer to distinguish the concepts because they belong to different parts of the system.

Decision latency is the delay between information and effective action.

Operational lead time is the delay after the action becomes effective until the physical or operational consequence occurs.

For a purchase order:

[ \text{effective response time}

\text{decision latency} + \text{supplier lead time} ]

This separation becomes important when the two behave differently.

Supplier lead time may be relatively stable while internal approval latency varies wildly. Or supplier lead time may depend on order quantity while internal latency depends on whether a recommendation hits an exception threshold.

Combining everything into one constant “lead time = 8 days” can hide the mechanism you actually need to improve.

Latency can be endogenous to the decision

This is where the problem gets more interesting.

Decision latency is not always an external constant.

The action itself may change how long execution takes.

For example:

  • orders under $25,000 auto-approve,
  • orders above $25,000 require director approval,
  • emergency freight requires another workflow,
  • a new supplier requires compliance review,
  • a truckload order executes through EDI while an unusual quantity generates a manual exception,
  • a large production change requires a setup approval.

Now latency depends on the decision:

[ \delta = \delta(x) ]

That creates a real economic tradeoff.

A theoretically better order may be operationally worse if it enters a slow approval path and arrives too late.

This is exactly the kind of thing that gets lost when the mathematical model is built separately from the operating process.

The decision variable is not always “quantity”

A useful framing question is:

What can we actually choose right now?

In a replenishment system, the decision may include more than quantity:

[ x_{i,t} = \text{order quantity for item } i ]

but also:

[ y_{i,t} = 1 \text{ if the order is expedited} ]

or:

[ a_{i,t} \in {\text{auto}, \text{manual}, \text{escalated}} ]

The policy might jointly choose quantity and execution path.

For example, expediting could reduce latency but incur a cost:

[ \min ; \mathbb{E}[\text{stockout cost} + \text{holding cost} + \text{expedite cost}] ]

subject to supplier capacity, MOQ, pack size, budget, receiving capacity, and approval rules.

Once framed this way, “process latency” is no longer something outside the optimization problem. It can become an economic decision.

Uncertainty belongs in the latency too

A common improvement is to replace a deterministic supplier lead time with a lead-time distribution.

Good.

But if internal execution latency is uncertain, model that too.

Suppose approval normally takes four hours but occasionally takes two days because an approver is unavailable.

Then:

[ \delta \sim P(\delta) ]

The relevant demand exposure depends on both demand uncertainty and latency uncertainty.

In simulation, this is straightforward to represent:

  1. observe the state,
  2. generate the recommendation,
  3. sample or replay the execution delay,
  4. evolve demand and other state variables during the delay,
  5. activate the decision,
  6. continue the system forward.

This produces a much more honest policy evaluation than pretending the action enters the system instantly.

Human review creates a policy layer

Many production optimization systems have a human in the loop.

That does not automatically make the system bad. It does mean the human behavior is part of the implemented policy.

Suppose the optimizer recommends x but planners modify 15% of recommendations.

The deployed policy is not:

[ x = \pi(S) ]

It is closer to:

[ x^{exec} = H(\pi(S), S, U) ]

where H represents the human review process and U represents information or judgment available to the planner.

The review also introduces latency.

If the planner overrides recommendations intelligently, that can add value. If review simply delays every order while changing almost nothing, the organization is paying for latency without receiving information value in return.

That is measurable.

Track:

  • recommendation timestamp,
  • review-start timestamp,
  • approval timestamp,
  • execution timestamp,
  • original recommendation,
  • executed decision,
  • override reason.

Then ask a very practical question:

What economic value are we getting from the delay?

If 99% of recommendations are approved unchanged after 18 hours, there is probably a process-design opportunity.

Constraints can change while the decision waits

Latency becomes especially dangerous in tightly constrained systems.

Imagine an allocation model that assigns scarce inventory at 6:00 AM.

The model sees 10,000 units available and allocates them across customers.

But the allocations are not committed until noon. During those six hours, another channel consumes 1,500 units.

The optimization was feasible at solve time and infeasible at execution time.

This is not necessarily a solver bug.

The state went stale.

For shared resources such as:

  • inventory,
  • cash,
  • dock capacity,
  • production capacity,
  • transportation capacity,
  • supplier capacity,

ask whether the resource is reserved when the model decides or only consumed when execution occurs.

That distinction changes the architecture.

You may need reservation logic, short-lived capacity holds, revalidation before execution, or a policy that explicitly protects against expected state drift.

Revalidation is often cheaper than pretending the state is fresh

One practical pattern is:

  1. solve using the best available state,
  2. hold the recommendation,
  3. immediately before execution, re-read critical state,
  4. verify that key constraints remain valid,
  5. execute or selectively re-optimize.

You do not always need to rerun the entire model.

A lightweight validation layer may check things such as:

  • inventory still available,
  • budget still available,
  • supplier still open,
  • MOQ still satisfied,
  • capacity reservation still valid,
  • recommendation has not aged beyond a threshold.

This is particularly useful when optimization is expensive but state changes are easy to detect.

Model age as a first-class production metric

Most teams log solver runtime.

They should also log decision age.

Useful timestamps include:

  • state_as_of
  • forecast_as_of
  • optimization_started_at
  • optimization_finished_at
  • recommendation_published_at
  • approved_at
  • transmitted_at
  • accepted_at
  • effective_at

From these, compute:

[ \text{state age at execution}

\text{effective time} - \text{state as-of time} ]

and:

[ \text{post-solve latency}

\text{effective time} - \text{optimization finish time} ]

Do not only report averages.

Look at p50, p90, p95, and p99. Operational failures often live in the tail.

A median approval delay of two hours can coexist with a p95 of 36 hours. The latter may dominate stockout incidents.

Solver runtime is part of decision latency

This also changes how to think about solver performance.

Suppose Model A produces a solution worth $1,005,000 after 90 minutes.

Model B produces a solution worth $1,000,000 after 4 minutes.

If both decisions execute tomorrow morning, the 90-minute solve may be completely fine.

If the decision controls same-day allocation and every minute of delay causes the state to drift, the faster model may produce better realized economics despite a slightly worse modeled objective.

The relevant comparison is not simply:

[ \text{objective value} ]

It is closer to:

[ \text{realized value after accounting for decision delay} ]

This is why solver tuning should start from the operating clock.

A 1% MIP gap may be irrelevant if waiting another 30 minutes for 0.1% changes the state enough to erase the gain.

A practical stopping policy

Instead of setting a time limit because “30 minutes seems reasonable,” define the operational deadline.

For example:

  • state snapshot: 2:00 AM,
  • downstream transmission deadline: 5:00 AM,
  • validation and publishing need 20 minutes,
  • safety buffer: 10 minutes.

Then the optimization budget is at most 150 minutes.

But even that may be too generous if state freshness degrades quickly.

A better stopping rule can combine:

  • incumbent quality,
  • remaining bound,
  • decision stability,
  • elapsed time,
  • expected cost of further delay.

Conceptually, continue solving while:

[ \text{expected value of more optimization}

\text{expected cost of additional latency} ]

You may not estimate both sides perfectly. The framing is still better than treating solve time as an isolated engineering metric.

Evaluate policies in closed loop

A static backtest often does this:

  1. reconstruct historical state,
  2. optimize,
  3. compare the recommendation with some benchmark.

That misses latency.

A stronger evaluation replays the operating process:

  1. reconstruct only information available at the historical decision timestamp,
  2. run the policy,
  3. apply historical or simulated decision latency,
  4. evolve the system during the delay,
  5. execute the action when it would actually have become effective,
  6. observe demand, receipts, constraints, and subsequent decisions,
  7. repeat.

Now you are testing the policy that can actually exist in production.

For inventory, useful metrics include:

  • realized gross margin,
  • stockout units,
  • fill rate,
  • lost sales,
  • inventory holding cost,
  • aged inventory,
  • expedite spend,
  • planner overrides,
  • decision latency,
  • state age at execution.

The last two should sit beside the economic metrics, not in a separate engineering dashboard nobody looks at.

Failure mode: using tomorrow’s information today

Latency creates a subtle backtesting leakage problem.

Suppose historical recommendations were generated Monday morning from a Sunday-night snapshot, but your backtest reconstructs inventory using Monday-end-of-day data.

The backtest now knows demand that occurred during the real decision-latency window.

The simulated policy looks smarter than the production policy could ever be.

The fix is point-in-time reconstruction.

Every input should answer:

Could the system actually have known this at the moment the recommendation was generated?

That includes forecasts, open orders, inventory, supplier acknowledgments, prices, capacities, and cancellations.

Failure mode: adding arbitrary safety stock to compensate

Teams sometimes discover that the production policy stocks out more than the model predicted and respond by increasing safety stock.

That may work operationally, but it can hide the real problem.

If the model assumes seven days of exposure while the process actually creates nine, adding a safety-stock multiplier is compensating for a missing timeline.

The policy becomes harder to interpret and harder to transfer to another business process.

Fix the state transition first. Then calibrate uncertainty protection.

Failure mode: measuring model latency but not process latency

Engineering teams often optimize a 12-minute solver down to 8 minutes while recommendations then sit in a planner queue for 14 hours.

The four-minute improvement may be technically impressive and economically meaningless.

Break total latency into components:

[ \delta_{total}

\delta_{data} + \delta_{solve} + \delta_{publish} + \delta_{review} + \delta_{transmit} + \delta_{accept} ]

Then attack the component that actually matters.

Sometimes the right optimization improvement is a stronger formulation.

Sometimes it is removing a manual approval.

Sometimes it is running the model three hours later so the state is fresher.

Sometimes it is moving the decision earlier so the supplier sees it before a cutoff.

That is decision engineering, not just mathematical optimization.

Failure mode: optimizing a decision after it is already effectively made

This happens more often than people admit.

A model may formally decide production quantities on Wednesday, but procurement already committed raw materials on Monday. Or an allocation model runs nightly even though sales representatives effectively promise the inventory to customers during the day.

The mathematical “decision variable” is then not actually free.

A basic framing test is:

At the moment this model runs, what choices remain reversible?

If a decision is already committed, represent it as state or a constraint. Do not pretend the optimizer still controls it.

Failure mode: ignoring calendar structure

A 24-hour delay on Tuesday is not always equivalent to a 24-hour delay on Friday.

Supplier cutoffs, weekends, holidays, warehouse schedules, and transportation calendars create discontinuities.

An order transmitted Friday at 5:05 PM may not be acknowledged until Monday morning.

Five minutes of internal delay just created roughly 60 hours of effective latency.

This is why calendar-aware simulation matters.

Represent the actual execution opportunities, not just continuous elapsed time.

Implementation architecture

A production decision system should make the timeline observable.

A useful architecture separates:

State builder — constructs point-in-time state and records state_as_of.

Policy engine — computes the recommended action from that state.

Recommendation store — persists the recommendation, model version, state version, objective, and diagnostics.

Approval or execution layer — records modifications, approval, transmission, and effective timestamps.

Outcome layer — records what happened after execution.

This gives you a full chain:

[ \text{state} \rightarrow \text{recommendation} \rightarrow \text{executed action} \rightarrow \text{outcome} ]

with timestamps at every boundary.

Without that chain, debugging becomes storytelling.

What to log for every decision

At minimum, I would want:

  • decision ID,
  • policy/model version,
  • state snapshot ID,
  • state timestamp,
  • forecast version and timestamp,
  • recommendation timestamp,
  • recommended action,
  • modeled objective contribution,
  • relevant binding constraints,
  • approval timestamp,
  • override flag and reason,
  • executed action,
  • transmission timestamp,
  • acceptance/effective timestamp,
  • realized latency components,
  • realized outcome metrics.

For stochastic systems, also log enough information to reproduce the scenario set or random seed used for evaluation when practical.

You should be able to take a bad operational outcome and reconstruct what the system knew, what it recommended, what humans changed, when the action became real, and what happened next.

A useful experiment: latency sensitivity

If you already have a simulator, run a simple experiment.

Evaluate the same policy under:

  • zero execution delay,
  • 2-hour delay,
  • 8-hour delay,
  • 1-day delay,
  • 2-day delay,
  • the empirical latency distribution from production.

Plot realized economics against latency.

You may discover the policy is insensitive to the first 12 hours and then falls off a cliff. Or you may find that a single missed supplier cutoff drives most of the damage.

That tells you where process improvement is worth money.

You can do the same with solver runtime. Evaluate whether additional solve quality compensates for the extra delay.

Latency can change which policy wins

This is one of the most important consequences.

Suppose Policy A is more sophisticated and produces better decisions with fresh state, but takes 90 minutes to run.

Policy B is simpler and runs in two minutes.

Under a zero-latency backtest, A wins.

Under the actual operating process, B may win because it acts on fresher information or catches an earlier execution window.

That does not mean sophisticated optimization is bad.

It means the comparison was incomplete.

The policy, computation, workflow, and execution mechanism form one decision system.

Benchmark the system.

What to do in practice

Start with one real decision process, not an enterprise-wide latency program.

Pick a replenishment run, allocation process, production schedule, or other recurring decision.

Draw the timeline from state snapshot to effective action. Put actual timestamps on it. Measure the distribution of each delay component from logs rather than relying on what the process document says.

Then do four things.

First, update the simulator or backtest so decisions become effective when they actually would in production.

Second, determine whether the latency is deterministic, stochastic, calendar-dependent, or decision-dependent.

Third, measure economic sensitivity to that latency. Do not assume every minute matters equally.

Fourth, decide whether the best intervention belongs in the model or the process. You might change the policy, reserve resources, add revalidation, automate approval, alter the solve deadline, or move the run closer to execution.

The goal is not zero latency.

The goal is to spend time only where the information or optimization gained during that time is worth more than the delay it creates.

The bigger point

Optimization is usually presented as choosing the best action given a state.

Production systems are messier.

The state is observed at one time. The model computes for some period. Humans or systems may review the result. The action becomes effective later. The world changes throughout that chain.

If you ignore that clock, you can build a mathematically excellent policy for a system that does not exist.

Treat decision latency the same way you treat demand, lead time, capacity, and cost: as part of the model of reality.

Because once the model leaves the notebook, when the decision happens is part of what the decision is.