Here's my verdict up front: food warehouses that run on FIFO instead of FEFO — first-expired, first-out — typically write off two to three times as much expired product. I've watched this play out across more than a dozen food distribution operations. And it's almost never a software problem. Most WMS platforms can allocate by expiry date just fine. The problem is that the expiry data going in is garbage, and nobody watches the alerts coming out.
People assume FIFO and FEFO are close enough. They aren't. First in is not first to expire. The same SKU received in March might be good through next June, while the batch received in May expires this November — that happens every single day in food warehousing. Ship by FIFO and the November lot sits in the back while the June lot goes out the door. By the time anyone notices, you're writing off full pallets. A frozen-food 3PL outside Los Angeles, roughly 60,000 square feet, learned this the expensive way a few years back: a full pallet of frozen shrimp sat two months past its date before anyone caught it. Tens of thousands of dollars, straight to disposal. Why? Their system didn't even have an expiry field. Picking was driven entirely by receipt date.
If the Expiry Data Is Garbage, FEFO Is Theater
FEFO stands on two data points: lot number and expiry date. In the WMS, both must be mandatory at receiving — no date, no receipt. That's the iron rule. The dumbest workaround I've seen: when receiving gets slammed, the system lets people skip the expiry entry and auto-fills 2099-12-31. Six months later, thousands of inventory records all "expire" in 2099, and the FEFO algorithm is sorting on fiction. You might as well not have an algorithm.
Date formats need standardizing too. Supplier labels are chaos: 06/08/26 on one carton, 08-JUN-2026 on the next, and some that print only the production date with no expiry at all. The receiving SOP has to pick one convention — year-month-day, expiry date only, never production date — and lock it in. Don't leave both a "production date" and an "expiry date" field open for the receiver to choose between. I learned that one the hard way: half the crew fills in one field, half fills in the other, and the system's expiry sort is wrong for half your inventory.
Inbound also needs a shelf-life validation rule: product arriving with too little remaining shelf life gets rejected or sent to QA hold. What counts as "too little" depends on the category. For a 12-month ambient product, anything under a third of its life left is a no-go; for a 45-day chilled product, I'd start worrying below half. There is no universal number here — set it by category and turnover speed, write it into the receiving SOP, and defer to your actual system and operation. The key is making it a hard system validation, not a laminated sign on the wall. Signs don't stop receivers. Pop-ups do.
One more trap: mixed lots from the supplier. Two expiry dates on the same pallet have to be received as two separate lots. Merge them into one because it's faster, and the system only ever sees one expiry date — the other half of the pallet becomes invisible to FEFO. I watched a warehouse do exactly this to save time, and the near-expiry half of every pallet kept getting deprioritized until it expired unnoticed.

An Alert Nobody Acts On Is Just Spam
Once the data is clean, you need warnings. I run three tiers: 90 days, 60 days, 30 days to expiry, with the WMS generating a daily expiry report pushed to the right owners. The tiers and day counts should vary by category — chilled and ambient can't share the same playbook. But here's the part everyone skips: every alert needs an owner and an action. At 90 days, the action is "tell sales to move it." At 60, it's "markdown or transfer plan." At 30, it's "start the disposal approval." An alert with no action attached is spam, and after three months nobody reads it.
The hardest thing to configure is the outbound allocation logic. Pure ascending-expiry allocation is theoretically optimal and practically miserable — it shreds pick paths, and your pickers end up walking half the building for one order. That's the real trade-off: expiry priority versus pick efficiency. My compromise: allocate by expiry first, but within the same wave, allow merging picks for lots whose expiry dates fall within a few days of each other. A few days doesn't matter; a few months does. Size that window by category — tight for chilled, loose for ambient. Don't chase the theoretical optimum. A 90-point plan your pickers actually follow beats a 100-point plan nobody executes.
One more configuration that separates working FEFO from decorative FEFO: don't let near-expiry stock die in deep storage. When the 60-day alert fires, the system should recommend moving that stock to the forward pick zone — closest to packing, easiest to grab. Physical positioning plus FEFO allocation is a double lock. Plenty of warehouses configure the allocation logic but never the slotting strategy, and then the near-expiry pallets sit at the back of the reserve area while pickers grab whatever's convenient. The system was right; human nature won.
What do you do with near-expiry stock? Three exits: markdown, donate, destroy. Markdown it to discount outlets or staff purchase — recover what you can. Donation is protected in the US by the Bill Emerson Good Samaritan Food Donation Act of 1996, which generally shields donors of not-yet-expired food from liability and can come with tax benefits — check with your tax advisor. And when it's truly unsalvageable: disposal with dual sign-off, photo documentation, and compliant destruction. The disposal workflow belongs in the system too — who requests, who approves, how it's destroyed, where the photos live. If the process isn't in the system, the process doesn't exist.
One footnote: FEFO isn't just for food. Pharma and cosmetics run the same logic. The only differences are tighter alert windows and stricter disposal compliance.
And one loop most warehouses forget to close: cycle counts. Don't just count quantities — verify expiry dates against the physical labels. A mismatch between the label and the system means someone bypassed the process at receiving or during a move. Track expiry discrepancies as their own count-variance category and review them monthly. The count is the most honest mirror your data will ever get.
Tomorrow morning, run one query in your WMS: how many inventory records have a blank expiry date, or a placeholder like 2099-12-31. Plug that hole first — nothing else in FEFO works without it.









