Data science · 11 min read

Demand forecasting for Shopify inventory

Which forecasting methods suit Shopify inventory, from seasonal naive to ETS, Prophet, LightGBM and Croston, and how to measure accuracy and set safety stock.

Inventory is where forecasting stops being an analytics exercise and becomes cash. Order too little and you lose sales and ad spend sending traffic to out-of-stock pages; order too much and working capital sits in a warehouse. The good news is that the methods that work for Shopify-sized catalogs are well understood. The hard parts are the data problems around them: sparse SKUs, stockouts and the wrong accuracy metric.

Which baseline should every inventory forecast beat?

Before fitting anything, build two benchmarks:

  • Seasonal naive: each forecast equals the last observed value from the same season. For weekly data with yearly seasonality, next year’s week 12 is this year’s week 12; for daily data with a weekly pattern, next Monday equals last Monday. Forecasting: Principles and Practice (FPP3) lists it alongside the mean, naive and drift methods as standard benchmarks.
  • Moving average: the average of the last n weeks. It is not one of FPP3’s four benchmarks, but it is what many teams already use in spreadsheets, so it is the bar the model has to clear in practice.

Then evaluate on a time-based holdout: fit on data up to a cutoff, forecast the next weeks, compare with what happened, and repeat for several cutoffs (rolling origin). If a sophisticated model cannot beat seasonal naive this way, it is adding complexity without accuracy.

When are ETS and ARIMA enough?

For a store with tens or a few hundred products with steady sales, per-product statistical models are often all you need.

  • Exponential smoothing (ETS) weights recent observations more heavily than older ones and handles level, trend and seasonality explicitly; the Holt-Winters method is its seasonal form. FPP3 describes it as generating reliable forecasts quickly for a wide range of series, and its state space form gives prediction intervals, which you need for safety stock.
  • ARIMA models the autocorrelations in the data instead of explicit trend and seasonal components. It is a good alternative when sales depend on recent sales in ways smoothing does not capture.

In Python, statsmodels covers Holt-Winters:

from statsmodels.tsa.holtwinters import ExponentialSmoothing

fit = ExponentialSmoothing(
    weekly_units, trend="add", seasonal="add", seasonal_periods=52
).fit()
forecast = fit.forecast(12)  # next 12 weeks

Yearly seasonality needs at least two full years of history to estimate. With less, fit weekly-pattern models on daily data, or borrow seasonality from the category level.

Is Prophet a good choice for Shopify sales?

Prophet, introduced by Facebook, is a regression model with trend, seasonality and holiday components. It is quick to set up (a dataframe with ds and y columns), handles multiple seasonalities and lets you list holidays and promotions explicitly, which is convenient for Black Friday and Cyber Monday.

On accuracy, FPP3 is direct: in its examples Prophet’s forecasts were worse than ETS and ARIMA, and the authors note it rarely gives better accuracy than the alternatives, although it is much faster to estimate on some problems. It works best on series with strong seasonality and several seasons of history. Use it as one candidate in the comparison, not as the default.

When do LightGBM-style global models win?

Per-series models learn from one product at a time. A global model is a single model trained across all SKUs, with features like recent sales lags, rolling means, price, discount flags, day of week, holidays, product category and inventory status. It can learn that a new variant in an established category behaves like its siblings, which per-series models cannot.

The strongest evidence comes from the M5 competition, which asked forecasters to predict 42,840 hierarchical Walmart unit-sales series. The organizers report that most of the leading methods they examined used LightGBM, that the winner combined LightGBM models trained per store, store-category and store-department, and that M5 was the first M competition where all top-performing methods were pure machine learning methods and significantly better than all statistical benchmarks.

The caveats for a Shopify brand:

  • Global models pay off with many related series. With 40 products, ETS per product is usually as good and far easier to maintain.
  • They need careful feature engineering and validation to avoid leaking future information, especially with lag features over multi-week horizons.
  • For counts, use an objective that fits the data. LightGBM supports poisson and tweedie objectives, which suit non-negative, zero-heavy sales better than squared error.

How do you forecast sparse SKUs and intermittent demand?

Most catalogs have a long tail: variants that sell zero units on most days. Daily per-SKU models do poorly here. Three tools help.

Croston’s method. It splits the series into the non-zero demand sizes and the intervals between them, smooths each with exponential smoothing, and forecasts demand per period as size divided by interval. FPP3 notes two weaknesses: it does not correspond to a statistical model, so there are no algebraic prediction intervals, and its forecasts are known to be biased. Variants such as SBA and TSB address these issues; the statsforecast library implements CrostonClassic and related models.

Aggregate, then allocate. Forecast at product or category level and split down to variants using recent sales shares. In hierarchical forecasting terms this is top-down; forecasting every variant and summing is bottom-up. FPP3 points out that bottom-level data is noisy and harder to forecast, which is exactly the variant problem. Whatever approach you use, forecasts should be coherent: variant forecasts should add up to the product forecast that purchasing sees.

Coarser time buckets. A SKU that sells three units a month is better forecast monthly than daily. Match the bucket to the reorder cycle.

Why do stockouts break demand forecasts?

When a product is out of stock, recorded sales are zero, but demand was not. Training on those zeros teaches the model that demand dropped, so it under-forecasts, so you order less, so you stock out again. It is a feedback loop.

The fix starts with data: record each SKU’s available inventory every day, so stockout periods can be identified. Then either:

  • mark sales on stockout days (and days with very low stock) as missing rather than zero, and let the model or an imputation fill them;
  • or include an in-stock flag as a feature in a global model and forecast with the flag set to in-stock.

The same logic applies to sold-out sizes within a product: if the medium is out, some medium demand shows up as large sales, and some disappears.

How should you measure forecast accuracy?

Avoid MAPE as your headline metric. FPP3 lists its problems: it is infinite or undefined when actual sales are zero and extreme when they are close to zero, and it puts a heavier penalty on negative errors than positive ones. At SKU level, zeros are routine.

Use these instead:

  • WAPE (weighted absolute percentage error): sum of absolute errors divided by sum of actual sales across the SKUs and periods you care about. It is unit-based, stays defined with zeros, and weights fast movers more, which matches their effect on inventory.
  • MASE (mean absolute scaled error, Hyndman and Koehler, 2006): the mean absolute error divided by the in-sample error of a naive forecast (seasonal naive for seasonal data). Below 1 means the model beats that benchmark; above 1 means it does not. It is comparable across products with very different volumes.
import numpy as np

# actual, forecast and train are NumPy arrays (use .to_numpy() on Series)
def wape(actual, forecast):
    return np.abs(actual - forecast).sum() / actual.sum()

def mase(actual, forecast, train, m=52):
    scale = np.mean(np.abs(train[m:] - train[:-m]))  # seasonal naive in-sample error
    return np.mean(np.abs(actual - forecast)) / scale

Also track bias (the sum of forecast minus actual, divided by actual). A forecast with acceptable WAPE that is consistently low will still cause stockouts.

How do you turn a forecast into safety stock?

A point forecast is the middle of a range. Ordering exactly that means stocking out roughly half the time demand exceeds it. Safety stock covers the uncertainty over the replenishment lead time.

The textbook starting point, assuming independent daily forecast errors and a fixed lead time:

  • Safety stock = z × σ × √L
  • Reorder point = forecast demand over the lead time + safety stock

Here σ is the standard deviation of daily forecast errors (from your holdout, not the standard deviation of sales), L is the lead time in days, and z sets the cycle service level: about 1.28 for 90%, 1.645 for 95% and 2.33 for 99% in-stock probability per replenishment cycle.

Refinements matter in practice. If supplier lead times vary, that variance has to be added. Errors are rarely independent day to day, so √L understates risk during promotions. And for intermittent SKUs, prediction intervals or simulated demand paths beat the normal approximation. Apply higher service levels to products where a stockout is expensive, such as hero products and items with paid traffic pointed at them, and lower ones to the long tail.

What does a practical forecasting setup look like?

  1. Clean order line data into daily or weekly units per SKU, with refunds and cancellations removed and stockout days flagged.
  2. Build seasonal naive benchmarks and a rolling-origin backtest.
  3. Fit ETS or ARIMA per product; add a global LightGBM-style model if you have hundreds of SKUs.
  4. Route intermittent SKUs to Croston-type methods or category-level forecasts.
  5. Choose models by WAPE, MASE and bias on the backtest, not by in-sample fit.
  6. Convert errors into safety stock and reorder points, and review them with purchasing every cycle.

Asabisoft builds this kind of pipeline for Shopify brands as part of its demand forecasting work; it is usually worth bringing in help once the catalog is too large to forecast by hand and stockouts are visibly costing paid traffic. For the customer side of the same planning problem, see LTV forecasting with under a year of data.

Key takeaways

  1. A model is only worth running if it beats a seasonal naive baseline on a time-based holdout.
  2. ETS and ARIMA are strong per-series defaults; global gradient-boosted models trained across many SKUs dominated the M5 retail forecasting competition.
  3. Most SKUs in a long catalog are intermittent; forecast them with Croston-type methods or at an aggregate level, not with daily per-SKU models.
  4. Sales during a stockout are a floor on demand, not demand; leaving those zeros in teaches the model to under-order.
  5. Prefer WAPE and MASE to MAPE, and size safety stock from forecast errors over the replenishment lead time.

FAQ

What is the best forecasting model for a Shopify store?

There is no single best model. Start with a seasonal naive benchmark, then compare ETS or ARIMA per product, and a global LightGBM-style model if you have many SKUs with shared patterns. Keep whichever wins on a time-based holdout measured with WAPE or MASE.

Is Prophet good for e-commerce demand forecasting?

Prophet is fast and handles strong seasonality and holidays conveniently, but Hyndman and Athanasopoulos report that it rarely beats ETS or ARIMA on accuracy in their examples. Treat it as one candidate to compare, not a default.

Why is MAPE a bad metric for inventory forecasts?

MAPE is undefined when actual sales are zero and explodes when they are close to zero, which is common at SKU level. It also penalizes over- and under-forecasts asymmetrically. WAPE and MASE avoid both problems.

How do I forecast products that sell only occasionally?

Use methods built for intermittent demand, such as Croston's method and its variants, which forecast the size of non-zero sales and the interval between them separately. Alternatively forecast at a higher level, such as product or category, and allocate down to variants.

Sources

  1. Hyndman & Athanasopoulos, Forecasting: Principles and Practice (3rd ed.) — Evaluating point forecast accuracy
  2. Forecasting: Principles and Practice (3rd ed.) — Forecasting with count data (Croston's method)
  3. Forecasting: Principles and Practice (3rd ed.) — Prophet model
  4. Forecasting: Principles and Practice (3rd ed.) — Single level approaches (hierarchical forecasting)
  5. Makridakis, Spiliotis & Assimakopoulos, The M5 Accuracy Competition: Results, Findings and Conclusions, International Journal of Forecasting
  6. Hyndman & Koehler (2006), Another look at measures of forecast accuracy (MASE)