Overview
This started with a simple question from the store:
“How do we know what will sell next?”
Up until this point, every purchase decision was reactive.
Something sells out → reorder it.
Something doesn’t move → stop buying (eventually).
That works… until it doesn’t.
With imported products, delays are long and demand is unpredictable. By the time you react, you’re already late.
So instead of reacting to the past, the goal here was: Can we reasonably predict the near future?
Not perfectly. Just better than guessing.
Why Forecasting Was Hard Here
1. Demand Was Noisy
- Some products sell daily
- Some sell once a week
- Some spike randomly
2. Data Was Sparse
- Many SKUs had very few data points
- ML models would overfit
3. Missing Context
- No marketing data
- No campaign signals
Design Philosophy
- Be directionally correct, not perfect
- Prefer stable signals over noise
- Make outputs usable
Architecture
Data Layer
- Daily sales per SKU
Processing Layer
- Aggregation in BigQuery
Forecasting Layer
- Rolling averages
- Weighted smoothing
Output
- 7–14 day demand forecast
Core Approach
Rolling Average
forecast = rolling_mean(last_n_days)
Weighted Forecast
forecast = (0.6 * last_7_days_avg) + (0.4 * last_30_days_avg)
Handling Intermittent Demand
- Used frequency + average sale size
Key Decisions
No Heavy ML
- Sparse data
- Need explainability
Short Horizon
- Focus on 7–14 days
Tradeoffs
- Simple models → less reactive
- No external data → limited context
Results
- Better restocking decisions
- Reduced stockouts
- Less over-ordering
Takeaway
You don’t need perfect forecasts to make better decisions.