Inventory Management: EOQ, Safety Stock & Newsvendor
How much to order and when. Learn why inventory exists and what it costs, ABC analysis, the EOQ model and its robustness, quantity discounts and production (EPQ) variants, reorder points, lead-time demand and safety stock for service levels, continuous (Q, R) vs periodic (T, S) review policies, the newsvendor model for perishable items, and inventory KPIs — with Python for EOQ, safety stock and the critical ratio.
Inventory buffers against uncertainty and enables economies of scale, but ties up cash, space and risks obsolescence — holding costs are typically 20–30% of item value per year. Too little inventory means stock-outs, lost sales and stopped production lines.
Inventory models balance ordering costs against holding costs, and shortage risk against safety stock, using demand forecasts and their errors.
An analogy
Inventory is like the water in your household tank: ordering a tanker is expensive each time, so you don't want to order daily; but a huge tank ties up space and money. You also keep a reserve for days when the tanker is late or you use more water than usual.
Why and what it costs
Types: raw materials, WIP, finished goods, MRO spares; purposes: cycle stock (batching), safety stock (uncertainty), anticipation stock (seasonality), pipeline stock (in transit), decoupling buffers. Costs: ordering/setup, holding (capital, storage, insurance, obsolescence, shrinkage), shortage (lost sales, expediting, downtime) and item cost.
EOQ and variants
EOQ assumes constant known demand, fixed ordering cost, instant delivery and no shortages. Extensions: EPQ when production is gradual, quantity discounts (evaluate EOQ at each price break and the break quantities), planned backorders, and multi-item joint replenishment. ABC analysis focuses control: A items (≈20% of SKUs, 80% of value) get tight control.
Uncertainty and review policies
Common policies:
- Continuous review (Q, R) — order Q when inventory position ≤ R (ROP); SS = zσ√L
- Periodic review (T, S) — every T, order up to S; protection interval T + L so SS = zσ√(T + L)
- (s, S) — order up to S when ≤ s
- Service measures: cycle service level (P(no stock-out per cycle)) vs fill rate (fraction of demand met)
- Lead-time variability adds: σ_LTD = √(L·σ_d² + d̄²·σ_L²)
Newsvendor, multi-echelon and KPIs
Single-period problems (fashion, newspapers, perishables, capacity reservations) use the newsvendor: order where the probability of demand ≤ Q equals the critical ratio. Multi-echelon inventory optimisation positions stock across a network (risk pooling cuts total safety stock by √n). KPIs: inventory turns, days of supply, fill rate, stock-out rate, obsolescence and carrying cost.
Formulas
- EOQ:
Q* = √(2DS/H) - Total annual cost:
TC = (D/Q)·S + (Q/2)·H (+ D·unit price) - Reorder point:
ROP = d̄·L + SS - Safety stock:
SS = z·σ_d·√L (demand variability) - EPQ (production):
Q* = √(2DS / (H(1 − d/p))) - Newsvendor:
critical ratio = C_u/(C_u + C_o); Q* = F⁻¹(CR)
Worked example: EOQ
Given: D 12 000, S ₹150, H ₹4
Find: Q* and orders/year.
- √(2 × 12 000 × 150/4)
Answer: 949 units, 12.6 orders/year
Worked example: Reorder point
Given: 48/day, L = 5 days, σ_d = 12, 95% service
Find: ROP.
- SS = 1.645 × 12 × √5 = 44
- ROP = 240 + 44
Answer: 284 units
Worked example: Newsvendor
Given: Demand ~ Normal(200, 40), CR 0.667
Find: Q*.
- z = 0.43
- 200 + 0.43 × 40
Answer: ≈ 217 units
EOQ, safety stock and newsvendor
import math
# EOQ, reorder point with safety stock, and total cost
D = 12000 # units/year
S = 150.0 # ordering cost per order
H = 4.0 # holding cost per unit-year
EOQ = math.sqrt(2 * D * S / H)
TC = D / EOQ * S + EOQ / 2 * H
print(f"EOQ = {EOQ:.0f} units, orders/year = {D/EOQ:.1f}, annual ordering+holding cost = {TC:.0f}")
d_daily, sigma_d, L = D / 250, 12.0, 5 # daily demand, std dev, lead time days
z = 1.645 # 95% cycle service level
SS = z * sigma_d * math.sqrt(L)
ROP = d_daily * L + SS
print(f"safety stock = {SS:.0f} units, reorder point = {ROP:.0f} units")
# Newsvendor: order quantity for a perishable item
price, cost, salvage = 10.0, 4.0, 1.0
Cu, Co = price - cost, cost - salvage
CR = Cu / (Cu + Co)
print(f"critical ratio = {CR:.3f} -> order the {CR*100:.1f}th percentile of demand")
# EOQ = 949 units, orders/year = 12.6, annual ordering+holding cost = 3795
# safety stock = 44 units, reorder point = 284 units
# critical ratio = 0.667 -> order the 66.7th percentile of demandAt the EOQ, ordering and holding costs are equal. The cost curve is flat near the optimum — ordering 20% more or less raises cost only ~2% — so practical lot sizes can round to pallet quantities. Safety stock protects against demand variability during the lead time; the newsvendor orders above median demand when underage (lost profit) costs more than overage (leftovers).
Common mistakes
- Wrong: Setting safety stock by rule of thumb (e.g. 2 weeks). — Right: Base it on demand and lead-time variability and a target service level.
- Wrong: Confusing cycle service level and fill rate. — Right: Choose the metric that matches the business goal.
- Wrong: Ignoring holding cost of capital. — Right: Include financing, obsolescence and storage (20–30%/yr).
Applications
- Retail replenishment: Store and DC reorder points.
- Manufacturing: Raw material and component lot sizing.
- Spare parts: Low-demand, high-value service parts.
- Hospitals: Drug and consumable stock control.
Key takeaways
- EOQ = √(2DS/H); cost curve is flat.
- ROP = d̄L + zσ√L.
- Choose service metric deliberately.
- Newsvendor: CR = C_u/(C_u + C_o).
Going further
- Multi-echelon optimisation: Placing safety stock across networks.
- Stochastic lead times: σ_LTD with variable supplier performance.
- Inventory with forecasts: Using forecast-error σ instead of demand σ.