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.