Skip to main content

Overview

The BOMs section defines what your products are made of. It is the structural foundation Production Planning relies on to translate downstream demand into upstream production, resource load, and raw-material procurement. Two object types live here:
  • BOMs — the production recipes for every item you make or buy, organized as a directed acyclic graph. A BOM with no components is a raw material; a BOM with components is an assembly. Multiple BOMs can produce the same entity when the recipe varies by configuration.
  • Configuration Templates — the possibility space for a configurable product: the decisions (option classes) and always-included materials that describe what a product can be. Walking a template through the Configurator produces a Configuration, and each iteration on it is captured as an immutable revision.
This page covers BOMs themselves. For how the two object types fit together, start with the BOMs & Configuration overview.

Entities

Every BOM produces an entity. An entity has a name, an optional description, and a set of attributes that define the dimensions along which members of that product family can differ — a canned-seafood entity might carry species, sourcing, and can_size attributes; a bracket entity might carry material_grade. Attributes come in five types: Entities live at the factory level and are shared across every model, BOM, and planning configuration. Renaming or deleting an entity affects every BOM that references it, so make the change deliberately.
Create the entity before any BOM that references it — if the entity is missing, the BOM write fails.

How BOMs Work

A BOM links a parent entity to zero or more child components. Each component reference points to another BOM — not to a bare entity. That distinction is what lets the graph carry different recipes for the same entity: the parent chooses which specific child BOM it wants, not just which entity. BOMs form a directed acyclic graph:
  • Every node is a BOM; edges are defined by a BOM’s component references.
  • A material can’t be part of its own BOM — cyclical dependencies are rejected on write.
  • The same child BOM can be referenced by many parents — it’s a graph, not a strict tree.
  • Every component quantity is an integer of at least 1, and defaults to 1 when omitted.

Material Classification

Material type is derived from a BOM’s position in the graph, never set by hand: Classification determines what each planning input accepts: demand orders accept only SKU entities, supply orders accept only RAW entities, and on-hand inventory and inventory goals accept any classification. See Demand & Supply.
A planning model carries its own BOM list, and the optimizer only sees BOMs in that list. Classification is evaluated against the graph the optimizer sees — so a BOM missing from the model’s list can quietly flip an intended SKU into RAW, or vice versa. When a demand order errors with “Only SKU entities are allowed in demand orders”, the usual cause is a missing BOM in the model, a finished good that has no components yet, or an unintended consumer — often a stale BOM left in the model’s list — that quietly reclassifies the intended SKU as an INTERMEDIATE.

Variant Conditions

One entity can have multiple BOMs, each covering a different region of the entity’s attribute space. Each BOM carries a variant — a list of conditions on the entity’s attributes that narrows which configurations this recipe serves. All conditions in a BOM must match (conjunction), and attributes the BOM does not mention are wildcards. A BOM with an empty variant is the default recipe for the entity.

Condition Types

Range defaults are lower_inclusive: true, upper_inclusive: false; both are configurable. When several BOMs for the same entity condition on the same attribute, they must all use the same condition type for it — one BOM cannot treat species as discrete_text while another treats it as a range. Mixed types on a shared attribute are rejected on validation.

Matching Orders to BOMs

Variants on demand orders, supply orders, on-hand inventory, and inventory goals are matched against BOM variants by subset, not exact match: for every attribute the BOM mentions, the input must carry the same attribute with a condition that is a subset of the BOM’s condition. Attributes the input carries that the BOM doesn’t mention are ignored; attributes the BOM mentions that the input omits cause the match to fail. This lets each BOM condition only on the recipe-relevant attributes while the order carries the full product spec. Partial specification is expected — an entity with five attributes may need only two BOMs if the recipe varies along one dimension. A BOM with an empty variant mentions no attributes at all, so it matches any input — this is how a default recipe resolves.

Mutual Exclusivity

When multiple BOMs exist for the same entity, their variants must be mutually exclusive so every input resolves to at most one BOM. Two BOMs are mutually exclusive when at least one shared attribute has disjoint conditions.
Two BOMs that condition on completely different attribute sets are not mutually exclusive — they can both apply to the same input, which is ambiguous and rejected on validation. Make sure variant BOMs for the same entity share at least one attribute with disjoint conditions.

Exploring the Structure

The BOMs page (BOMs & Supply in the sidebar) offers two views — All Entities and All BOMs — and lets you drill in from either direction:
  • Down the tree (explosion) — from a parent BOM, expand through intermediates to the leaf raw materials, with quantity per unit at each edge.
  • Up the tree (where-used) — from any BOM, trace every parent assembly that consumes it, with the quantity consumed at each level.
Both directions are covered in depth — including quantity rollups and running them through Dexter — in BOM Explosion & Where-Used.
Run a where-used check before changing a shared component. Any parent that consumes it moves with the change.

Creating a BOM

  1. Create the entity first, if it does not exist (Create entity on the BOMs page). Name it, describe it, and add the attributes the recipe or the demand side needs to distinguish variants.
  2. Create the BOM for that entity. Add each component (a reference to another BOM) with a quantity of at least 1 — a component without an explicit quantity defaults to 1.
  3. If more than one recipe applies to this entity, add a variant condition that narrows this recipe to the region of the attribute space it serves.
  4. Save.
Order matters. Build bottom-up: raw materials (leaf BOMs) before the assemblies that consume them, layer by layer up to the finished good. Cycles are rejected.
When a BOM’s structure or quantities come from source data — an ERP export, a parts list, a customer document — capture the derivation as a pipeline bound to the BOM so the recipe traces back to its source.

BOMs and Planning

A planning model carries an explicit BOM list — the BOMs the optimizer is allowed to see for that model. A BOM outside the list is invisible to that model even if it exists elsewhere in the factory; this is the most common source of “why is my SKU classified RAW?” confusion. Given its BOM list, the optimizer uses BOMs to:
  • Derive intermediate production from downstream SKU demand
  • Enforce per-interval resource capacity, given each BOM’s resource requirements
  • Resolve each demand line to the correct variant BOM
  • Respect precedence — a parent cannot be produced before its components are available
Each planning run is a scenario against the model, carrying demand orders (tagged with weight, penalty_curvature, buffer, and a hard/soft deadline_type), supply orders, on-hand inventory, inventory goals, and per-interval resource capacity. Changes to a BOM take effect on the next run — existing results are historical.

Best Practices

  • Build bottom-up. Author leaf BOMs first, then the layers above.
  • Prefer one entity with variant BOMs to many entities. Products that share production structure but differ along specific dimensions are the same entity with attributes, not separate entities.
  • Condition variants on the fewest attributes that actually drive the recipe. Every extra attribute in a variant is a place the demand match can fail.
  • Ensure shared attributes across variant BOMs of the same entity. Disjoint attribute sets are rejected as ambiguous.
  • Verify the planning model’s BOM list after structural changes — classifications can shift.
  • Name entities descriptively. Human-readable names survive reorganization and read cleanly in errors; opaque part numbers do not.
  • Use descriptions as operational context. They are the durable notes the next person reads.
  • Land a single baseline run before branching into planning scenarios.