+1 (726) 224-7339

Building a Demand Planning and S&OP Model in Anaplan

Most demand planning projects start with the wrong question. Teams ask "what statistical method should we use?" long before they have agreed who owns the number, at what level it is agreed, and what happens when sales and supply disagree. Anaplan is very good at answering the second set of questions, which is why S&OP is one of the platform's strongest use cases — and why a demand model built as a forecasting engine alone almost always stalls at adoption.

This tutorial walks through building a demand planning and sales and operations planning (S&OP) model in Anaplan end to end: the dimensional design, the baseline forecast, the enrichment layers where planners and sales add their view, the consensus lock, the supply-constrained comparison, and the executive S&OP review page. It assumes you are comfortable with modules, SUM, LOOKUP, and time ranges. If your model structure discipline is shaky, read the DISCO blueprint first — demand models punish sloppy dimensionality faster than any other use case.

Step 0: settle the planning grain before you build anything

The single decision that determines whether this model runs in four seconds or four minutes is the planning grain — the combination of dimensions at which the demand plan is stored and agreed.

Three separate grains exist in every real S&OP process, and conflating them is the classic mistake:

GrainTypical dimensionsUsed for
Statistical grainSKU x Ship-To x WeekBaseline forecast generation
Planning grainProduct Family x Region x MonthWhere humans plan and agree
Execution grainSKU x Location x WeekWhat supply and deployment consume

Planners should never be asked to touch a SKU-week grid with two million intersections. Generate statistics fine, agree coarse, disaggregate back down. Write the three grains on a whiteboard and get the S&OP process owner to sign off before you create a single list.

Sizing sanity check, done on paper first:

SKUs                    12,000
Ship-To locations          400
Weeks in horizon           104
Naive cell count    = 12,000 x 400 x 104 = 499,200,000 per line item

That number is why demand models get built on sparse combination lists, not on the cross product. Build a flat combination list (often called SKU-Location or DFU, "demand forecast unit") containing only the intersections that actually transact, and dimension your fine-grained modules by that list plus Time. A 12,000 x 400 cross product may collapse to 60,000 real DFUs — a four-order-of-magnitude saving. Polaris changes this calculus for genuinely sparse data; our Hyperblock or Polaris guide covers when to switch engines instead.

Step 1: lists and hierarchies

Build the structural skeleton:

  • Product hierarchy — Category > Subcategory > Product Family > SKU. Production list at every level (the business adds SKUs constantly).
  • Customer / geography hierarchy — Region > Country > Channel > Ship-To.
  • DFU list — a flat, numbered list of live SKU-Location combinations, loaded and maintained by an integration, with properties pointing at SKU and Ship-To.
  • Time — monthly for the planning horizon (24 to 36 months), with a weekly time range for the near-term statistical and execution layers. Use time ranges, not one giant model calendar; see Versions, Scenarios, and Time Ranges.
  • Demand streams list — Baseline, Promotion, New Product Introduction, Cannibalization, One-Off Event. Small, builder-controlled, not a production list.
  • Versions or a scenario list — Consensus, Sales View, Statistical, Budget, Prior Cycle.

Then the System modules that make everything else readable:

SYS01 SKU Properties          (Product Family, Category, ABC/XYZ class, Lifecycle Stage, Active flag)
SYS02 Ship-To Properties      (Region, Country, Channel)
SYS03 DFU Properties          (SKU, Ship-To, Planning Family, Launch Date, Discontinue Date)
SYS04 Time Settings           (Current Month flag, Frozen Horizon flag, In Planning Window flag)

SYS04 deserves special attention. The frozen horizon — the near-term period where supply is committed and the demand plan can no longer be changed — is a Boolean by month, driven off one input date. Every write-back rule and every Dynamic Cell Access formula in the model should reference it rather than re-deriving the logic. See our Dynamic Cell Access tutorial for the locking pattern.

Step 2: history and cleansing

Statistical forecasts are only as honest as the history behind them. Load shipment (or, better, consumption) history into a DAT01 Shipment History module at the DFU x Week grain, then build a cleansing layer rather than editing history in place:

CAL01 History Cleansed
  Raw History          = DAT01 Shipment History.Qty
  Outlier Upper Bound  = Rolling Median + 3 * Rolling MAD
  Is Outlier           = Raw History > Outlier Upper Bound AND SYS01 SKU Properties.Active
  Planner Override     -- input, sparse, used for known one-offs
  Cleansed History     = IF NOT ISBLANK(Planner Override) THEN Planner Override
                         ELSE IF Is Outlier THEN Outlier Upper Bound ELSE Raw History

Keeping raw, override, and cleansed as three separate line items means a planner can always answer "why is the baseline low for this SKU?" without opening the source system. Add a Demand Streams split here too if you have promotional history worth isolating: a baseline trained on promoted weeks will forecast permanent promotion.

Two cleansing rules that save arguments later: never cleanse inside the current open month, and never cleanse a DFU with fewer than the minimum history periods you require — flag it as a new-product case instead and route it to the NPI process.

Step 3: the baseline forecast

You have three viable options, and choosing between them is an architecture decision, not a preference.

Anaplan Forecaster (formerly PlanIQ) runs the statistical and ML models on Anaplan's side, writes results back into a module, and gives you backtesting and explainability. This is the default choice for most builds. See our Forecaster setup guide for history preparation, driver configuration, and forecast value added tracking.

An external forecasting engine — a data science team's model in Python, or the demand engine already embedded in your ERP — landing results into Anaplan through Data Orchestrator or CloudWorks. Right when a mature statistical capability already exists; our integration tooling comparison covers the plumbing.

Native formulas in Anaplan — moving averages, seasonal indices, Holt-Winters style exponential smoothing implemented in line items. Adequate for stable, low-SKU-count businesses and genuinely useful as a transparent fallback, but do not attempt to rebuild a modern ML stack in formulas.

Whichever you pick, land the result in a dedicated module and never let planners write into it:

CAL02 Statistical Forecast   (DFU x Week)
  Stat Forecast Qty       -- written by Forecaster / integration / formula
  Model Used              -- text, for explainability
  Forecast Accuracy MAPE  -- from backtesting
  Confidence Band Upper / Lower

Then aggregate to the planning grain in one hop, using SUM against a System module mapping rather than a chain of lookups:

CAL03 Statistical at Planning Grain   (Planning Family x Region x Month)
  Stat Forecast = CAL02 Statistical Forecast.Stat Forecast Qty[SUM: SYS03 DFU Properties.Planning Family, SUM: SYS03 DFU Properties.Region]

Step 4: the enrichment layers

This is where an S&OP model earns its keep. The consensus number is not a single input; it is a stack of transparent adjustments, each owned by someone:

CAL04 Demand Plan Build   (Planning Family x Region x Month)
  1. Statistical Baseline    = CAL03.Stat Forecast
  2. Planner Adjustment      -- input, demand planner
  3. Promotion Uplift        = CAL05 Promotions.Uplift Qty
  4. NPI Ramp                = CAL06 New Products.Ramp Qty
  5. Sales Intelligence      -- input, regional sales
  6. Consensus Demand        = 1 + 2 + 3 + 4 + 5
  Variance to Stat %         = IF Statistical Baseline = 0 THEN 0
                               ELSE (Consensus Demand - Statistical Baseline) / Statistical Baseline

Three rules make this stack work in practice.

One owner per row. If two roles can type into the same line item, nobody owns the number. Enforce it with Dynamic Cell Access driven by a role-to-line-item System module, not by trust.

Every adjustment carries a reason. Add a text or list-formatted Adjustment Reason line item next to each input. Reviews go faster when the deck already says "+8% Q3, distributor stocking".

Surface the variance, always. Variance to Stat % on the review page is the single most effective governance device in a demand model. Bias becomes visible, and visible bias corrects itself within two cycles.

Track forecast value added over time — whether each enrichment layer actually improved accuracy against the naive and statistical baselines. Layers that consistently add nothing should be removed from the process, and that conversation only happens if the model measures it.

Step 5: disaggregation back to the execution grain

Supply needs SKU-Location-Week. Planners agreed Family-Region-Month. Bridge them with a proportional split derived from recent history or the statistical forecast itself:

CAL07 Disaggregation   (DFU x Week)
  Stat Share of Family = IF Family Stat Total = 0 THEN 0 ELSE Stat Forecast Qty / Family Stat Total
  Consensus Qty        = CAL04.Consensus Demand[LOOKUP: SYS03.Planning Family, LOOKUP: SYS03.Region] * Stat Share of Family

Two refinements matter. Guard every division against a zero denominator, and hold the split ratios as a periodically refreshed snapshot rather than recalculating them live from a huge history module — a static ratio module keeps the calculation chain short and the numbers stable through a review cycle.

Step 6: the supply-constrained view and the gap

S&OP is the meeting where unconstrained demand meets constrained supply. Model both sides and, critically, the gap:

CAL08 Supply Response   (Planning Family x Region x Month)
  Unconstrained Demand  = CAL04.Consensus Demand
  Available Supply      = DAT02 Supply Plan.Qty
  Constrained Plan      = MIN(Unconstrained Demand, Available Supply)
  Gap Qty               = Unconstrained Demand - Constrained Plan
  Gap Revenue           = Gap Qty * SYS05 Price.Avg Price
  Gap Margin            = Gap Qty * SYS05 Price.Avg Margin

Expressing the gap in revenue and margin, not just units, is what turns an operational review into an executive one. "We are 40,000 units short" prompts a shrug; "we are 40,000 units short, which is £2.1m of revenue and £700k of margin concentrated in two families" prompts a decision. If those gap numbers need to flow into the financial plan, connect this module to the P&L rather than exporting to a spreadsheet — that link is the whole argument for connected planning, and our modern data architecture guide covers keeping it clean.

Step 7: the cycle, in the model

An S&OP model without an embedded calendar becomes a spreadsheet with better dimensions. Build the cycle in:

  1. Data refresh (working day 1-2). History and actuals load; statistical forecast regenerates.
  2. Demand review (day 3-6). Planners and sales enrich. Adjustment cells open, baseline locked.
  3. Consensus lock (day 7). An action snapshots Consensus Demand into a Locked Consensus module stamped with the cycle. Adjustment cells close via DCA.
  4. Supply review (day 8-10). Constrained plan loads; gaps compute.
  5. Executive S&OP (day 11-12). Gap decisions are recorded as inputs in the model, with owner and due date.
  6. Publish (day 13). Approved plan exports to ERP and to the financial forecast.

Steps 3 and 5 are the ones teams skip and later regret. The locked snapshot is what lets you measure forecast accuracy honestly at any lag, and recorded decisions are what make the next review start from "did we do what we said?" rather than a blank page. Route the sign-off through Anaplan Workflow so approvals are tasks with owners and timestamps rather than emails.

Step 8: the pages planners will actually use

Build three New UX pages, not thirty:

Demand Review (planner-facing) — a filtered DFU or family grid with the enrichment stack as rows, variance-to-stat conditional formatting, a history-versus-forecast chart, and a reason-code column. Default the filter to the planner's own portfolio using a user-driven System module.

Exception Dashboard — the page planners open first. Not a grid of everything: a ranked list of items that need attention. High absolute variance to statistical, MAPE above threshold, DFUs with no forecast, adjustments without a reason code, families where the gap exceeds a materiality floor. Rank by revenue impact, cap the list at what a human can process in a morning.

Executive S&OP — one page: consensus versus constrained versus budget, gap in margin, top five gap drivers, accuracy trend, and open decisions with owners.

If you are still on Classic dashboards, our New UX migration guide walks the transition.

Measure the model, not just the demand

Instrument accuracy from day one, at the planning grain and at lags that match your lead times:

  • MAPE and weighted MAPE at lag 1 and lag 3, by family and region.
  • Bias (signed forecast error) — persistent one-directional bias is a process problem, not a maths problem.
  • Forecast value added — accuracy of the consensus plan versus statistical versus a naive seasonal baseline.
  • Adjustment hit rate — how often each enrichment layer moved the number closer to actuals.

Publish these in the same model, visible to the same people who make the adjustments. Nothing improves forecast quality faster.

Common failure modes

  • Planning at the statistical grain. Planners abandon the model within two cycles. Aggregate for humans.
  • A cross-product model with no combination list. Cell counts explode, the model slows, and every fix afterwards is a rebuild. Get sparsity right at design time; the formula performance tuning guide can only recover so much.
  • No locked snapshot. Accuracy becomes unmeasurable because the "forecast" you compare to actuals has been edited since.
  • Promotions buried in the baseline. Separate demand streams or accept permanently inflated forecasts.
  • A consensus number nobody owns. Governance beats algorithms. Assign owners per row, per family, per region.
  • Ignoring the frozen horizon. If planners can edit a period supply has already committed, the plan and reality diverge silently.

Where we help

We build demand planning and S&OP models in Anaplan for manufacturers, distributors, and consumer brands — dimensional design, statistical setup with Forecaster, the consensus process, and the supply gap bridge into the financial plan. That work sits across our Anaplan model design and build practice and our supply chain management consulting.

If you have a demand model that planners have quietly abandoned in favour of spreadsheets, that is a recognisable pattern with a recognisable fix. Get in touch and we will scope a review.