Short note. A compact reference, correct as far as it goes. It will be expanded into a full guide with a worked example and an interactive demonstration.
Problem
You order a product repeatedly to meet steady demand. Order too little too often and ordering costs (setup, shipping) pile up; order too much and holding cost (warehouse space, capital tied up) eats the savings. EOQ finds the sweet spot — closed-form, no solver required.
When to use it
Any inventory item with roughly constant, known demand and no meaningful uncertainty. It’s the starting point every inventory model builds on, even though real demand is rarely this tidy — see Newsvendor for the uncertain-demand version.
Formulation
With annual demand D, fixed ordering cost K per order, and holding cost
h per unit per year, total annual cost as a function of order quantity
Q is:
TC(Q) = (D / Q) * K + (Q / 2) * h
Minimizing over Q (take the derivative, set to zero) gives the classic
closed form:
Q* = sqrt(2 * D * K / h)
Code sketch
import math
def eoq(annual_demand, order_cost, holding_cost):
return math.sqrt(2 * annual_demand * order_cost / holding_cost)
Q_star = eoq(annual_demand=12000, order_cost=75, holding_cost=2.5)
No optimization solver needed — this is a one-line closed-form answer, not a MILP.
Pitfalls
- EOQ assumes constant demand, constant lead time, and no stockouts allowed — real inventory almost always violates at least one. Treat it as a reasonable starting point or a benchmark, not a final production policy.
- Quantity discounts break the clean formula — you end up comparing EOQ against each discount breakpoint rather than solving a single closed form.
- If demand is uncertain enough that stockout risk actually matters, EOQ is the wrong tool entirely; reach for a newsvendor-style model instead.