Most grocery apps are checklists.
Grocery Queue is a model of what is disappearing from your kitchen.
Instead of manually deciding what belongs on a shopping list, you tell the app what you have, give it a rough initial estimate of how long it should last, and then update it occasionally as you buy and consume things. It estimates when each item will run out and continuously ranks everything by urgency.
The result is not a list of things you might buy someday. It is a queue of what is becoming important next.
The problem: which store is worth walking to today?
The app came from a small but persistent annoyance. I have several grocery stores within walking distance and visit one almost every day, but choosing one still required reconstructing the state of my kitchen in my head.
The useful question was not merely What groceries do I need? It was:
Given what I am running out of, which store is most worth walking to today?
That seemed like exactly the kind of problem software should eliminate.
One queue, not several shopping lists
Different groceries have different store constraints. Milk and eggs belong to Whole Foods, ground beef to Trader Joe’s, and liver to Publix, while potatoes and bananas can come from several stores.
Before Grocery Queue, deciding where to go meant mentally scanning several overlapping lists and figuring out what was actually urgent.
Now there is one global queue. If its most urgent items cluster at Trader Joe’s, that is probably today’s walk. If liver is about to run out, Publix becomes relevant. If I already know I am going to Whole Foods, I can filter the same queue to see what matters there.
The stores are not separate shopping lists. They are constraints on the same underlying inventory model.
From inventory to urgency
For each item, Grocery Queue estimates a depletion rate and a current inventory . The simplest intuition is
Something with three weeks left should mostly disappear from my attention. Something likely to run out tomorrow should move toward the top.
That is the central distinction from an ordinary shopping list: a shopping list stores intentions; Grocery Queue stores an estimate of a changing physical state and predicts when intervention will be necessary.
Learning from sparse observations
The initial depletion rate is deliberately only a guess. As I use the app, actual observations gradually replace it.
The important trick is that purchases and counts provide different information.
Suppose the last exact count was at time , I purchased a total of units since then, and the next count is at time .
The amount actually consumed is
over the interval
So a purchase does not itself tell the model how much I consumed. It only tells it that inventory increased. Consumption becomes observable when another count closes the interval.
Grocery Queue maintains two weighted sufficient statistics: accumulated consumption evidence and accumulated time evidence . The estimated depletion rate is simply
When a new count arrives, old evidence is exponentially discounted and the new observation is added:
where
Here is the time of the previous evidence update and is the evidence half-life.
The half-life adapts to the item. Grocery Queue estimates a typical purchase cycle from recent purchase intervals and uses
The cycle is estimated from the median of up to the five most recent valid purchase intervals.
That means something I buy every few days can adapt relatively quickly, while something I buy every few months retains useful historical evidence for much longer.
The conceptual separation is simple:
Counts tell the model how much was consumed. Purchase quantities maintain inventory. Purchase timing determines how quickly old evidence should be forgotten.
Predicting what remains
Inventory estimation is anchored to the most recent exact count.
Let be that count, recorded at time , and let be everything purchased since then. At time , estimated inventory is
The predicted time remaining is then
That value ultimately drives the queue.
So underneath a very mundane grocery interface is a small state-estimation problem: infer the current inventory from sparse observations, learn its dynamics, predict when it reaches zero, and rank the actions that will soon become necessary.
Constant-space learning
One property I particularly wanted was that the model should not grow with the history of the item. History is evidence used to update the model; history is not itself the model.
At any moment, the relevant state is represented by the sufficient statistics and , plus a small fixed amount of recent purchase-cycle information. The app does not need to retain every egg count, carton of milk, or purchase event to estimate the current depletion rate.
Updating the model is therefore in the number of historical purchase and inventory events. Whether an item has been tracked for two weeks or five years, the work required for a new observation does not grow with its history.
That matters both computationally and conceptually: the application maintains a compact model of the present instead of accumulating an ever-growing log and repeatedly recomputing the past.
Local by design
Grocery Queue has no account, server, or cloud database. The model lives in the browser.
After the first visit, the complete application works offline and can be installed as a PWA.
That fits the use case: this is something I open while walking around and shopping. It should not need a network connection, login, synchronization service, or backend just to tell me whether I need eggs.
Grocery Queue turns the kitchen into a continuously changing priority queue:
see what is disappearing, see where it can be replaced, and pick today’s walk.