FEFO (First Expired, First Out): A Practical Guide to Rotating Dated Stock

FEFO (first expired, first out) is a stock rotation rule: you ship whatever expires soonest, no matter when it landed on your dock. If you move food, pharmaceuticals, cosmetics, lab reagents, or anything with a shelf life, this one rule decides whether product leaves as revenue or leaves as a write-off. Below is the method, a worked example, the exact decision rule, and how to run it without living inside a spreadsheet.
What FEFO actually means
FEFO sorts your picking and shipping queue by expiration date. The lot with the nearest expiry goes out first. That sounds obvious until you hit the trap: the oldest arrival is not always the one that expires first. A shipment that arrived last week can carry a shorter shelf life than one that arrived a month ago, because of how the supplier stored it, how far along its production run was, or which batch you happened to receive.
That is why FEFO is a separate discipline from FIFO (first in, first out). FIFO ranks stock by receipt date. FEFO ranks it by expiry date. When those two dates line up, the two methods behave identically. When they diverge, FIFO quietly ships the wrong lot and leaves your soon-to-expire stock rotting on the shelf.
FEFO vs FIFO vs LIFO
Three rotation methods get confused constantly. Here is the short version.
| Method | Ships first | Best for | Main risk |
|---|---|---|---|
| FEFO | Nearest expiry date | Perishables, pharma, dated stock | Needs expiry captured per lot |
| FIFO | Earliest received date | Uniform stock with steady shelf life | Ships wrong lot when expiry varies |
| LIFO | Most recently received | Non-perishables, some accounting rules | Oldest stock can expire in place |
If your products carry expiry or best-before dates, FEFO is the correct default. FIFO is a decent approximation only when every lot of a SKU has the same shelf life and you always receive in date order. LIFO almost never makes physical sense for perishables; it is mostly a cost-accounting concept.
Worked example: where FIFO loses money
You stock a single SKU of protein bars in three lots.
- Lot A: received Jan 2, expires Aug 1, quantity 400
- Lot B: received Jan 10, expires Jun 15, quantity 300
- Lot C: received Jan 20, expires Sep 1, quantity 500
An order comes in for 300 units in February.
Under FIFO, you pick Lot A first because it arrived earliest. You ship 300 bars from Lot A, leaving 100 of A, all of B, and all of C on the shelf. Lot B still expires Jun 15. If demand does not clear those 300 units of B before mid-June, you write them off. At a $1.10 landed cost, that is $330 in the bin plus disposal time.
Under FEFO, you pick Lot B first because it expires soonest (Jun 15). The 300 units that were about to become dead stock go out the door as revenue. Lots A and C, with their later expiries, wait safely. Same order, same warehouse, opposite financial outcome.
The lesson: FIFO optimizes for arrival order. FEFO optimizes for the thing that actually costs you money, which is the clock.
The FEFO decision rule
The core rule is one line:
Pick from the lot with the earliest expiry date that has available quantity and still meets the customer's minimum remaining shelf life.
That last clause matters more than most operators expect. Retailers, distributors, and hospitals often require a minimum percentage of shelf life remaining on delivery. A grocery chain demanding the "half-life rule" will reject anything under 50 percent shelf life remaining, even if it has not expired.
Calculate remaining shelf life like this:
remaining shelf life % =
(expiry_date - ship_date) / (expiry_date - manufacture_date) * 100
So a bar manufactured Jan 1, expiring Sep 1, shipped Jun 1, has (Sep 1 - Jun 1) / (Sep 1 - Jan 1) = 92 days / 243 days = about 38 percent remaining. That fails a 50 percent buyer even though it is nowhere near its expiry. Under strict FEFO you would ship it first, but the receiving-side rule can force you to divert it to a less demanding channel or discount it early. Build that check into your pick logic, not into a post-rejection scramble.
How to run FEFO in five steps
- Capture expiry at receiving. If the expiry or lot number does not get recorded when stock arrives, FEFO is impossible downstream. Scan or key the lot and date on the receiving dock, every time, no exceptions.
- Store by lot with the date attached. Keep the expiry bound to the physical quantity, not to the SKU in aggregate. One SKU can hold four live expiry dates at once.
- Sort picks by expiry, not by location. This is where most warehouse setups fail. Location-based picking grabs the nearest bin. FEFO has to override that and route the picker to the earliest-expiry lot, even if it is a few slots further down. Your system should generate the pick list already sorted.
- Run an aging report and alert early. Do not wait for expiry day. Flag anything crossing a threshold (say 30 or 60 days out) so you can promote, discount, or transfer it. The documentation on stock reports covers how to schedule these.
- Quarantine and write off cleanly. Expired stock needs a one-way door out of pickable inventory, with the write-off logged for accounting and audit.
Where FEFO breaks down
FEFO fails for boring, mechanical reasons, not exotic ones.
- No expiry captured at receiving. The single most common failure. Garbage in, no rotation out.
- Mixed lots on one shelf. If Lot B and Lot C share a bin with no separation, pickers grab whatever is in front, and your careful sort is fiction.
- Location picking silently overriding expiry. A basic system optimizes the walk path and ignores dates.
- Multi-location blind spots. Stock expiring in Warehouse 2 is invisible to a manager staring at Warehouse 1, so it dies while a sister site backorders the same SKU.
- Spreadsheets that do not scale. A manual tab works for one location and 50 SKUs. It collapses at three sites and a few thousand lots, and the errors are expensive.
If you are automating any of this, expose expiry and lot data through an API so your pick logic, alerts, and reporting all read the same source of truth. The REST and GraphQL API makes lot-level expiry queryable so downstream tools can enforce FEFO consistently.
Running FEFO without the spreadsheet
Inventoros handles lot and expiry tracking out of the box: it records expiry per lot at receiving, sorts pick lists by earliest expiry across multiple locations, and fires webhooks or aging alerts before stock goes dead. It is free, open source (MIT licensed), and self-hosted, so your dated-stock data stays on your own server. See the features list for multi-location stock, lot tracking, and alerting.
FAQ
What is the difference between FEFO and FIFO?
FIFO ships the oldest arrival first (sorted by received date). FEFO ships the soonest to expire first (sorted by expiry date). They match when stock arrives in expiry order, but diverge whenever a newer shipment has a shorter shelf life. For anything dated, FEFO protects margin better because it targets the clock, not the calendar of arrivals.
Is FEFO legally required?
Not by name. But regulations like FDA food safety rules, GMP for pharmaceuticals, and most retailer supply agreements effectively require it by demanding you never ship expired product and often mandate minimum remaining shelf life on delivery. FEFO is the practical method that keeps you compliant. Check the rules for your specific industry and region.
Does FEFO need barcode or lot tracking?
Yes, in practice. FEFO depends on knowing each lot's expiry date, and the reliable way to capture that is scanning a lot or batch code at receiving. You can run it manually at tiny scale, but past a few dozen SKUs across one site, lot-level tracking is what makes the rotation trustworthy.
How do I handle products without expiry dates?
Fall back to FIFO for those SKUs and reserve FEFO for dated stock. A good system lets you set the rotation method per product, so shelf-stable items rotate by receipt date while perishables rotate by expiry, all in the same warehouse.