Decision: Layered Canonical + Transformation Model
Date
2026-05-13
Stage
Late discovery / pre-v0 build.
Context
The product is a centralised data layer for AU music retail. Early framing treated it as "one canonical product record served to all consumers." Conversation has refined this: retailers want canonical inputs but retain their own preferences for how the data lands in their stack (variant grouping policy, field naming, output format, taxonomy override, display-value form).
A single-layer canonical model that tries to satisfy all retailer preferences either collapses to lowest-common-denominator (helps no one) or grows retailer-specific bleed back into the canonical record (becomes a per-retailer build, not a platform).
Confirmed facts
- Every AU brand has a single exclusive distributor — so two retailers stocking the same brand receive the same source data. The input side of the platform is shared by construction.
- Retailers diverge on output preferences (variant model, field naming, export shape, taxonomy adoption depth).
- Sweetwater's ~300+ standardised facets per category exist as a public reference for the canonical layer's depth target.
- Per-retailer customisation around supplier-data work is real today — each retailer reshapes the same supplier data differently for their stack.
Assumptions
- Retailer divergence is primarily about presentation and transformation, not about the underlying truth of what a product is.
- Standardised facet values (with optional display variants like "HH" vs "Dual Humbucker") are tractable at the canonical layer.
- The transformation layer can be configurable enough to absorb retailer divergence without per-retailer code.
Options considered
Option A — Single canonical record, all retailers consume identically
The platform decides one shape; retailers either accept it or do their own post-processing externally.
- Pro: simplest model. Lowest platform engineering cost.
- Con: retailers will reject it — they want different things and the platform's "one shape" will always be wrong for someone. Pushes the transformation work back to the retailer, defeating the platform's value prop.
Option B — Per-retailer canonical (effectively, per-retailer copies)
Each retailer gets their own canonical record, customised at canonical-record time.
- Pro: every retailer's needs met exactly.
- Con: not a platform. Becomes per-retailer consulting/integration work. No shared infrastructure benefit.
Option C — Layered: shared canonical + per-retailer transformation
Canonical layer is one shape, identical across all consumers, and is the moat. A separate transformation layer applies retailer-specific configurable mappings to produce retailer-shaped outputs.
- Pro: shared infrastructure where it matters (categories, facets, identity, base fields). Retailer freedom where it matters (output shape, variant model choice, taxonomy adoption). Adding a new retailer is a transformation config, not a canonical-record change.
- Con: two-layer design is more involved to build than one layer. Transformation editor is its own product surface. Requires discipline to keep retailer preferences from leaking into the canonical layer.
Tradeoffs
- More design work upfront. A layered model needs clear separation between canonical truth and retailer view. Sloppy separation early causes pain forever.
- Transformation editor becomes a product surface. Retailers need a UX to configure their own mappings. Non-trivial work but inherits patterns from existing PIM tooling.
- Canonical-layer governance is real. Adding a new facet, deprecating an old one, choosing canonical values — all become ongoing curation work, not one-time setup.
Risks
- Bleed-back into canonical. Pressure to "just add this one field for retailer X" will erode the shared-layer purity. Governance discipline matters.
- Lowest-common-denominator drift. If canonical-layer decisions are taken by retailer consensus, the layer becomes thin. The platform must be opinionated about canonical truth even when retailers disagree.
- Transformation editor scope creep. Mapping configuration can grow to consume disproportionate engineering effort. Keep the editor's surface small until v1 evidence justifies expansion.
Recommendation
Adopt Option C as the load-bearing design. Build v0 around the layered model from day one. The v0 build's purpose is, in part, to prove the layered design works — that two retailer-shaped outputs can be derived from one canonical record without bleeding back into the canonical layer.
What this unlocks
- The v0 scope memo can name its load-bearing thesis precisely (H5 in concept-narrative).
- Canonical-layer governance becomes a separate, scoped concern from output flexibility.
- Adding new consumer outputs (new POS shape, new retailer profile, new file format) is a transformation config — bounded work, not a canonical-record change.
- The platform's value prop becomes legible: shared work where shared work is possible; retailer freedom where retailer preferences are real.
What remains unresolved
- The exact API/SDK shape that consumers use to invoke the transformation layer.
- The governance process for canonical-value decisions (curated by us, supplier-input, retailer-voted, AI-assisted with human approval — likely a mix).
- The transformation editor's UX (which becomes a product in its own right).
- The boundary cases where retailers want the canonical record to be different (not just transform differently). Policy: canonical is opinionated; retailers transform on the way out.