Inventory Is a Prediction Problem, Not an Accounting Problem
For the first two years, our chicken filling par-level was the same every Sunday: last week’s usage plus 20%. It’s what the spreadsheet template said to do. It’s what the restaurant consultant said to do. It’s what most POS systems auto-generate for you if you turn on par-level alerts.
It cost us about $180 a week in wasted chicken filling. Over a year, that’s a vacation.
The mistake was treating inventory as an accounting problem: how much did we use, add some slack, write that down. Inventory is a prediction problem. Par levels are forecasts. And the right number isn’t "last week + 20%" — it’s whatever value hits a service level you explicitly chose.
The accounting view (wrong)
The pattern is everywhere:
par_level = last_week_usage * 1.2
# Or: average of last 4 weeks * 1.2
# Or: whatever the POS alert says
This has two problems:
- The 20% has no justification. It’s a vibe. On weeks where your demand distribution is tight, 20% is too much. On weeks where demand has a fat tail (catering order risk, weather shock), 20% is too little.
- It doesn’t tell you what you’re paying for. "20% cushion" buys you some stockout protection, but how much? If you run out twice a month, is that because 20% is too low, or because your usage is more variable than the mean suggests?
The prediction view (right)
Re-phrase the question. Instead of "how much should I prep?", ask:
“How much do I prep so I stock out less than X% of the time?”
That X is your service level. It’s a policy choice you make once:
- 90% service level = stock out ~3 times per month
- 95% = stock out ~1-2 times per month
- 99% = almost never, but you’ll waste more
Higher service level = more cushion = more waste. Lower service level = less waste = more stockouts. You cannot escape this tradeoff. You can only make it deliberate.
The math, such as it is
This is the classic newsvendor problem that operations-research textbooks have solved for a century. The answer, for a normally distributed demand with mean μ and standard deviation σ, is:
par_level = mu + z_score(service_level) * sigma
Where z_score comes from a z-table (Excel: NORM.S.INV(service_level)):
| Service level | z-score |
|---|---|
| 90% | 1.28 |
| 95% | 1.64 |
| 99% | 2.33 |
So if your chicken-filling usage averages 14 lbs/day with a standard deviation of 3 lbs, and you want to stock out only 5% of the time:
par_level = 14 + 1.64 * 3 = 18.9 lbs
Compare that to the old "last week + 20%" — if last week you used 14 lbs, that gave you 16.8 lbs. You’d run out ~19% of the time, not 5%. The old rule was secretly running a ~80% service level and nobody knew it.
The spreadsheet version, for humans
You don’t need Python. A spreadsheet with one column of daily usage, a running mean, a running standard deviation, and the par formula is enough:
A: date
B: daily_usage
C: mean_last_28d = AVERAGE(OFFSET(B2,-28,0,28,1))
D: stdev_last_28d = STDEV(OFFSET(B2,-28,0,28,1))
E: service_level = 0.95
F: z_score = NORM.S.INV(E2)
G: par_level = C2 + F2 * D2
Update it weekly. Your par level now moves in response to how variable demand has been, not just how much. A week with a steady, predictable rhythm gives you a lower par. A week with a catering order in the middle gives you a higher par. The cushion adjusts itself.
What we saw after switching
On chicken filling specifically, between four weeks before switching and eight weeks after:
| Metric | Before | After (95% SL) |
|---|---|---|
| Avg par level | 17.2 lbs/day | 16.1 lbs/day |
| Avg waste (lbs) | 2.8/day | 2.3/day |
| Stockouts/month | 4-5 | 1-2 |
| Weekly waste cost | $245 | $202 |
About $180/month saved on one ingredient. Scaling the same policy across the 6 perishable ingredients we were tracking got us close to the $180/week figure from the opening. Meaningful money for a business at our volume.
Also: knowing the stockout rate was chosen, not happening to us, changed how we thought about everything else. When a key wholesale account called asking if we could cover a last-minute order, we could look at par-level cushion and know whether yes was safe. Before, that was a gut call.
Handling the wrinkles
Demand isn’t normal
Strictly, the newsvendor formula above assumes normally-distributed demand. Restaurant demand usually isn’t — it’s often right-skewed (a few big days, many small ones). Two practical fixes:
- Split demand by day-of-week. Monday demand and Saturday demand are two different distributions; modeling them as one gives you too-wide variance.
- For the very skewed items, use the empirical quantile of the last 28 days’ demand instead of mean+σ. In a spreadsheet:
PERCENTILE.INC(range, service_level). That’s distribution-free and usually more accurate for small samples.
Service level isn’t always 95%
High-margin items, high-visibility items ("if we run out of empanadas on a Saturday night we lose the customer forever") want a 98-99% service level. Low-margin, easily-substitutable items can run at 85-90%. Set it per ingredient, not globally.
Lead time matters
If restocking takes 2 days instead of overnight, your par level needs to cover 2 days of demand variability, not 1. The math scales: sigma * sqrt(lead_time). For most restaurant perishables with daily prep, lead time is 1, so you can ignore this.
The pattern, one more time
Accounting view: "count what we used, pad it, write it down."
Prediction view: "the par level is a forecast of a quantile of next-period demand; choose the quantile deliberately."
Same math powers real-time trading systems, ad bid caps, server-capacity planning, hospital bed allocation. It’s the same problem shape. At ZenHodl the equivalent is choosing a Kelly fraction — another explicit service-level policy that you pick once and then measure, rather than tuning from vibes. The kitchen version is smaller-stakes but the shape is identical.
Three takeaways
- Every "cushion" you add is an implicit service-level choice. Make it explicit.
- For small data, use empirical percentiles instead of mean+σ.
PERCENTILE.INCis your friend. - Review service-level targets quarterly, not par levels weekly. The policy is the thing you maintain. The par level falls out of it.
Next: why point estimates lie to small-business owners and what to report instead.