Demand Forecasting by Store and SKU
ML forecasts demand at store, channel, and SKU level from sales history, seasonality, promotions, weather, and local events so planners can set more accurate inventory targets.
Retail processPlanBuyPriceStockSellFulfillReturnClear
By Don, DoneThat’s AI coach · updated
Who this is for
This page is for demand planners who set store-SKU inventory targets before orders firm up. You already work with weekly sales history, promo calendars, and assortment changes. The gap is usually not more data; it is turning noisy local signals into a forecast you can trust enough to set a target against.
A model that scores demand at store, channel, and SKU level helps you move past chain averages that overstock quiet stores and starve busy ones. It does not replace your judgment on service level, pack size, or commercial risk. The model proposes a demand outlook; you still set the target.
What the model uses
Store-SKU forecasts work best when inputs describe both the item and the place it sells.
Sales history is the backbone: units sold by store (or fulfillment node), channel, and SKU over enough weeks to show seasonality and trend. Thin history for new SKUs, new stores, or sparse sellers should not produce a confident number. In those cases the system should return empty or incomplete output rather than inventing a false baseline.
Seasonality and calendar effects capture recurring patterns: holidays, back-to-school, weather-driven categories, and day-of-week effects that differ by store cluster.
Promotions and price matter because lifts are rarely uniform. A national promo can spike one region and barely move another. Feed planned and historical promo flags, depth, and duration so the model can separate base demand from temporary lift.
Weather and local events help for categories sensitive to temperature, storms, or foot traffic (sporting events, festivals, school calendars). These signals refine short-horizon outlooks; they do not override a missing sales record.
Assortment and availability context prevents training on stockouts as if they were true demand. Where possible, note out-of-stocks, planogram changes, and channel switches so the forecast reflects unconstrained demand rather than past failures to supply.
Related planning work often sits nearby: Localized Assortment Planning decides what to carry; this forecast sizes how much. Site decisions in New Store Site Selection Model change the store set the forecast must cover. Promo timing in Promotion Calendar Optimizer feeds the lift assumptions this model consumes.
How planners use the forecast
- Pull the outlook for the planning horizon. Review base demand and promo-adjusted demand by store-SKU (and channel where fulfillment differs).
- Check coverage and confidence. Confirm which SKUs and stores have enough history. Empty cells mean “do not auto-target”; escalate to analogs, category defaults, or manual entry.
- Set the inventory target. Convert forecast demand into a target using your service-level policy, lead time, pack constraints, and safety stock rules. The forecast is an input to that calculation, not the order quantity itself.
- Reconcile exceptions. Flag stores with large week-over-week swings, promo overlaps, or recent resets. Adjust targets where commercial or operational constraints override the model.
- Publish and measure. Lock targets for the cycle, then compare forecast vs. sell-through after the week closes to tune bias by cluster or category.
Human-in-the-loop is explicit at step 3: the model forecasts demand; the planner sets the target. Automation that skips that step usually ships either excess or empty shelves when local conditions diverge from the average.
Where forecasts go empty on purpose
Sparse sellers, brand-new doors, and one-week test SKUs often lack a stable pattern. Forcing a number trains planners to distrust the whole file.
Prefer empty or “insufficient history” output when:
- Sell weeks below your minimum threshold for that category
- Stockout-dominated history that cannot be reliably unconstrained
- Structural breaks (major remodel, channel cutover) without enough post-change weeks
- Promo-only history with no clean base period
Empty output is an operational signal: use sister-store analogs, category elasticity, or a manual seed, then re-enable ML once history is thick enough. That keeps the trusted portion of the file usable for automated target drafts.
Quality checks before you lock targets
Treat forecast quality as a weekly discipline, not a one-time model score.
- Bias by store cluster and category. Persistent over-forecast in one region means targets will lock in excess; under-forecast burns service.
- Promo vs. base separation. If lift bleeds into base, non-promo weeks will be fat; if lift is ignored, promo weeks stock out.
- Channel consistency. Ship-from-store and ecommerce demand should not double-count or silently drop when fulfillment rules change.
- Outlier review. Top movers and weather-sensitive SKUs deserve a planner pass even when the model looks stable.
- Target vs. forecast gap. Large systematic gaps between your locked targets and the model outlook may be good (policy) or bad (habit). Track both so you know which.
When these checks pass, store-SKU forecasting shortens the path from history to a defendable target. When they fail, fix inputs or leave the cell empty rather than polishing a weak number.
Practical rollout notes
Start with categories that have dense weekly history and clear promo calendars. Keep planners in the loop for target setting from day one. Expand to long-tail SKUs only after empty-output rules and analog workflows are clear. Align promo and assortment teams so the signals this forecast depends on stay current; otherwise local accuracy decays even if the model itself is sound.
Is this worth automating for you?
Whether this pays back depends on how much time it takes your team today. Most teams estimate that from memory, and the estimate is usually wrong in one direction or the other. This one is rated high effort to implement, so the baseline matters more than usual.
DoneThat reconstructs where the time actually went, with no timers to forget, so you can measure the baseline before committing to a project and check the gain afterward.
Measure the baseline first