Data · Inventory

Inventory Is a Prediction Problem, Not an Accounting Problem

April 2026 · 8 min read

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:

  1. 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.
  2. 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:

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 levelz-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:

MetricBeforeAfter (95% SL)
Avg par level17.2 lbs/day16.1 lbs/day
Avg waste (lbs)2.8/day2.3/day
Stockouts/month4-51-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:

  1. Split demand by day-of-week. Monday demand and Saturday demand are two different distributions; modeling them as one gives you too-wide variance.
  2. 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

  1. Every "cushion" you add is an implicit service-level choice. Make it explicit.
  2. For small data, use empirical percentiles instead of mean+σ. PERCENTILE.INC is your friend.
  3. 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.