All posts

Shelf-Life-Constrained Production Scheduling: Sizing Runs So Perishable SKUs Don't Expire

Shelf-Life-Constrained Production Scheduling: Sizing Runs So Perishable SKUs Don't Expire Before They Sell

Every food and beverage scheduler has lived both failure modes on a dated SKU. Run too little and you stock out mid-week, chasing an emergency short run and disappointing a customer. Run too much — usually "while we're set up, let's just make a bigger batch and save the changeover" — and three weeks later a warehouse manager is photographing pallets of short-dated product headed for markdown or landfill.

The frustrating part is that the standard lot-sizing math actively pushes you toward the second mistake. Economic order and production quantity models reward larger batches because they amortize setup cost across more units. That logic is sound — as long as product lives forever. In food and beverage, it doesn't. A yogurt, a fresh salsa, a cold-brew coffee, and a bag of artisan bread all carry a hard ceiling that no changeover-savings argument can overcome: the date on the package.

This post lays out a structured way to schedule against that ceiling. The goal is a run size that respects perishability first and economics second — so you hold your fill rate and keep write-offs low at the same time.

First, define your real shelf-life budget

Shelf life is the length of time a product can be stored before it becomes unfit for use, consumption, or sale. For packaged perishable food, that's expressed as an advisory best before, a mandatory use by, or a freshness date, depending on the product and jurisdiction (Wikipedia: Shelf life).

The critical mistake schedulers make is planning against the total shelf life printed on the label. You never get to use all of it. By the time finished goods are available to sell into the market, several chunks of the clock have already been spent — and the retailer takes another chunk off the end.

Think of it as a saleable shelf-life window:

Saleable window = Total shelf life
                − Production & QA hold (micro tests, release)
                − Distribution transit (plant → DC → retailer)
                − Retailer minimum-remaining-shelf-life requirement

That last term catches a lot of teams off guard. Most retail buyers enforce a minimum remaining shelf life on receipt — they will reject product that arrives with less than, say, 75% or 80% of its life left. So on a 30-day product, after a 2-day QA hold, 3 days of transit, and a retailer rule that rejects anything under 21 days remaining, your saleable window to produce, ship, and sell might be a fraction of what the label implies. That window — not the label number — is the constraint your schedule has to respect.

Why classic lot-sizing needs a perishability guardrail

The right lot-sizing baseline for a company that makes its own product is the Economic Production Quantity (EPQ) model. First formalized by E. W. Taft in 1918, EPQ minimizes total inventory cost by balancing fixed setup cost against holding cost. Unlike the classic EOQ, EPQ assumes stock is received incrementally as it is produced, rather than arriving all at once — which is exactly how a CPG line replenishes finished goods (Wikipedia: Economic production quantity).

EPQ is a useful anchor. But it optimizes only three cost terms: setup, holding, and — in stockout-aware variants — a shortage penalty. It has no term for expiration. Perishable inventory systems add a distinct outdating cost: a write-off charged per unit that expires unsold, layered on top of ordering, holding, and penalty costs (ScienceDirect: heuristics for perishable inventory systems).

That missing term is why EPQ misleads you on perishables. When you leave outdating cost out of the equation, the model happily recommends a batch larger than the shelf-life window can absorb — because on paper, holding cost is cheap relative to another changeover. Add the write-off cost back in, and the economically "optimal" batch shrinks, sometimes dramatically.

The core rule: cap the run at the shelf-life-feasible quantity

Here is the practical rule that keeps schedulers out of trouble. Compute the maximum feasible batch from the shelf-life window, then compare it to your EPQ/EPEI batch, and take the lower of the two.

Max shelf-life-feasible batch ≈ demand rate × saleable window − safety stock

A worked mini-example

Suppose a fresh dip SKU has:

  • Total shelf life: 30 days
  • Production/QA hold: 2 days
  • Transit to DC + retailer: 3 days
  • Retailer minimum-remaining requirement: rejects under 18 days

Saleable window = 30 − 2 − 3 − 18 = 7 days to actually move the product.

If average demand is 900 units/day, the shelf-life-feasible batch is roughly 900 × 7 = 6,300 units, before you carve out safety stock. Now suppose your EPQ math — chasing changeover savings — says the "optimal" run is 11,000 units. That larger batch represents over 12 days of supply on a product that only has a 7-day saleable window on the front end. You would be building product that is guaranteed to age out before it can sell through.

The rule says: cap the run at the shelf-life-feasible quantity. Run 6,300 (less safety stock), not 11,000.

The implication is uncomfortable but unavoidable: perishable SKUs usually need more frequent, smaller runs. You accept higher changeover cost as the deliberate price of avoiding write-offs. For fast-moving, short-dated products, that might mean producing several times a week rather than building a monthly mountain.

Reconciling the cap with changeovers and the schedule

More frequent runs collide directly with changeover economics and with production-wheel thinking. If you've built an Every Product Every Interval (EPEI) wheel, a shelf-life cap can force a tighter interval on specific SKUs than the wheel's default cadence.

The release valve is not to abandon the cap — it's to make changeovers cheaper and smarter so the extra runs hurt less. That's the whole case for SMED and for sequence-dependent changeover scheduling: if you order runs so that setups are short and clean, the cost of an extra perishable run drops, and the shelf-life cap stops feeling like a tax. As we've written in the hidden cost of changeovers, the goal is to shrink changeover cost until run-frequency decisions are driven by demand and shelf life — not by fear of the setup.

The governing principle: when the shelf-life-feasible quantity is smaller than the changeover-optimal quantity, shelf life wins on the master schedule. Write-offs are a hard cash loss and a food-safety-adjacent risk; a changeover is a recoverable cost you can engineer down.

Safety stock and service level for dated goods

With non-perishable SKUs, the reflex against demand variability is simple: carry more safety stock. On perishables, that reflex backfires — buffer inventory ages too. The safety stock you built to protect against a demand spike becomes tomorrow's write-off if the spike doesn't come.

This is the central tension in perishable supply planning. Modeling of perishable finished goods under lead-time uncertainty shows that planning on expected lead time significantly undershoots the target service level — you thought you were at 98% and you're really lower. Meanwhile a naïve execution policy can overshoot, holding more than needed and producing unnecessary outdating (ScienceDirect: perishable supply planning under lead-time uncertainty).

The takeaway for schedulers: you can't set safety stock on perishables by service level alone. You set it against a target service level with an explicit outdating tolerance — an accepted, deliberate write-off percentage. If you demand near-zero stockouts and near-zero waste on a short-dated, spiky SKU, the math simply won't close; you have to choose the balance point consciously rather than discover it in the write-off report. Segmentation helps here: our note on ABC-XYZ segmentation for scheduling and safety stock is a good way to decide which SKUs earn a fatter buffer and which should run lean and frequent.

FEFO on the floor: making the plan executable

A perfect shelf-life-aware plan collapses if the warehouse ships the wrong pallet. The issuing discipline that protects your scheduling assumptions is FEFO — First Expired, First Out. FEFO is a stock-rotation approach for products with limited shelf life: the unit with the nearest expiration date is served or shipped first, which minimizes waste of otherwise-marketable finished goods (Wikipedia: First Expired, First Out).

FEFO depends on data. To execute it reliably you need batch-level date and lot tracking, remaining-shelf-life visibility at the pallet, and — increasingly — shelf-life prediction to drive smarter allocation. Product-driven and sensor-based approaches to shelf-life prediction are being used specifically to make FEFO reliable and cut expiration losses (ScienceDirect: product-driven FEFO reliability).

The common execution gaps that silently defeat a good schedule:

  • Mixed lots on a single pallet or slot, so date order is invisible at pick time.
  • Hidden aged stock tucked behind newer production because the floor defaults to easiest-to-reach (effectively LIFO).
  • No remaining-life visibility, so pickers can't distinguish a 20-day pallet from a 6-day one.

Fix these and your shelf-life cap actually holds. Ignore them and even a conservative run size ages out in the racks.

A practical decision framework

Work this sequence for each perishable SKU:

  1. Compute the saleable window — total shelf life minus QA hold, transit, and retailer minimum-remaining requirement.
  2. Establish demand rate and variability — average daily demand plus a read on spikiness.
  3. Set the shelf-life-feasible max batch — demand rate × saleable window, net of safety stock.
  4. Compare to your EPQ/EPEI batch and cap — take the lower of economic-optimal and shelf-life-feasible.
  5. Size perishable-aware safety stock — with an explicit, accepted outdating tolerance rather than service level alone.
  6. Enforce FEFO — batch dating, remaining-life visibility, no mixed-lot confusion.
  7. Monitor the right KPIs — write-off / outdating %, short-dated aging, and fill rate, watched together.

What "good" looks like: a low outdating rate and the target fill rate held simultaneously. If one is only achievable by wrecking the other, your run sizes or your service targets need revisiting — not your warehouse team's effort.

How an agentic scheduler handles this automatically

Manually maintaining shelf-life caps across hundreds of SKUs — each with its own window, retailer rules, and demand pattern — is exactly the kind of grinding constraint math that gets skipped under pressure. An agentic scheduler encodes the shelf-life-feasible cap, the FEFO issuing assumption, and the service-level-with-outdating-tolerance target as first-class constraints, so the generated schedule respects perishability by default instead of relying on someone to catch the oversized batch before it hits the line. For more on that constraint-first, headless and agentic approach, see the linked overview.

Sources

More from the journal