Any inventory app lives or dies on one thing: how painful it is to add items. If logging groceries takes real effort, people stop doing it within a week, and the inventory drifts out of date until it's useless.
So the first real decision behind Expireless wasn't about features. It was about data entry. And the obvious answer — scan the barcodes — turned out to be the wrong one.
The problem with barcodes
Barcode scanning sounds clean. Point the camera, beep, item added. The math is what kills it.
A normal shopping trip is 30 to 50 items. Barcode scanning means 30 to 50 separate actions: pick up the product, find the barcode, line up the camera, wait for the beep, put it down, repeat. After carrying everything in from the car, nobody wants to stand there and scan forty things one at a time. The system that asks for that is the system people quietly abandon.
There's a second problem that's less obvious until you hit it. Barcodes only help if the code is in a database that knows the product — and store brands are badly covered. When we tested against real receipts, Walmart's own barcodes were poorly represented in the public databases. The scan would succeed and still come back with nothing useful.
And even when a barcode resolves perfectly, it tells you what the product is. It does not tell you when the carton you just bought expires — which is the one piece of information an expiry tracker actually needs.
Why receipts close most of the work
A receipt is a record of exactly what entered the house on one trip. One scan captures the whole run — all 40 items at once, instead of 40 separate beeps.
That single difference is most of the battle. The friction that kills inventory apps is the per-item effort, and a receipt collapses it to one action. In our own testing, a typical receipt of 46 items would come through with around 43 landing correctly on their own. The work that used to be forty manual entries became checking a short list and fixing a couple of things.
How the app actually reads a receipt
Different stores print receipts differently, so there are really two paths.
Some stores — Walmart, for example — print a barcode reference on each receipt line. There the app reads that code and checks it against its own product database. We had to grow this database ourselves, precisely because the public ones didn't cover these store items well enough — but instead of filling it by hand, it self-extends: every time the app recognizes a new product, that item gets added, so coverage compounds with use. It already holds around 8,000 barcodes across US and European products — enough to cover roughly 80% of a typical regular shopping trip on its own — and it keeps growing with every scan.
Other stores — Costco and Sam's among them — don't put barcodes on the receipt at all. Just abbreviated names. There the app works the other way around: it first expands the shortened name, then matches it against the database, and pulls the rest of the details from there. A barcode scanner is useless on a receipt that has no barcodes. A reader that understands the line works either way.
Expanding those names is harder than it sounds. A receipt line like GV NDL WID isn't just three abbreviations — it's "Great Value" (a Walmart brand), "noodles," and "wide," and the words aren't even in readable order. Turning that into "Great Value Wide Noodles" takes more than a lookup table; the system has to recognize what the product actually is and reassemble it the way a person would write it. That's the kind of thing a dictionary of abbreviations chokes on and Expireless handles.
Either path ends in the same place: the item gets a real name, a category, and a sensible default shelf life.
Why shelf life is set per product, not per category
This is the part most apps get lazy about. A category-level default says "milk lasts X days" and moves on. But two cartons of milk aren't the same: pasteurized milk and ultra-pasteurized milk sit in the same category and have completely different shelf lives. Bread from a hypermarket bakery and a packaged loaf from a brand like Harris are both "bread" and keep for very different lengths of time.
So the default shelf life is keyed to the specific product, not the broad category. The app sets a reasonable estimate — roughly half of the typical shelf life as a safe default — and you can adjust it when an exact date matters. Most of the time the default is close enough to be useful; when it isn't, fixing one field is faster than typing the whole item from scratch.
What it skips on purpose
A grocery receipt isn't all food. The same Walmart trip that brought home chicken and broccoli also has hair color, wax, and paper towels on it. The app filters non-food items out automatically, so the kitchen inventory stays a kitchen inventory instead of a copy of the whole receipt. You're tracking what you'll eat, not what you'll clean with.
Where you still type by hand
No system reads everything. Produce from a farmers market with no receipt, something you cooked yourself, a gift jar from a neighbor — those still get added manually. The honest version is this: receipt scanning handles the bulk of a normal grocery run, and you fill the gaps. The point was never to eliminate typing entirely. It was to make the everyday case — a full cart from one store — close to effortless, so the inventory stays current instead of slowly going stale.
That's the whole reason the app starts with the receipt. Fast and mostly automatic beats precise but tedious, because the tedious system is the one that ends up abandoned in a drawer.