- A supplier sends a product file with a column named Mfg.
- The storefront wants to show a familiar brand.
- If the platform copies Mfg into one generic specification, every downstream feature has to guess what the supplier meant.
- For a B2B marketplace built on Medusa, we modelled Brand and Manufacturer as separate optional product identities.
The client problem
A supplier sends a product file with a column named Mfg.
The storefront wants to show a familiar brand. Procurement wants to analyse spend by the company that made the product. Search needs stable facets. An invoice may need the purchased identity years after the live catalogue has changed.
If the platform copies Mfg into one generic specification, every downstream feature has to guess what the supplier meant. If it copies the same value into both fields, it creates confidence without evidence.
For a B2B marketplace built on Medusa, we modelled Brand and Manufacturer as separate optional product identities. Each has canonical records and known aliases. Imports map them independently. Search projects them independently. Orders snapshot both at purchase time.
They can carry the same name for a particular product. That does not make them the same business dimension.
The client problem: one catalogue label answers two different questions
Brand is the commercial identity a buyer recognises. Manufacturer is the organisation responsible for making the product.
Sometimes they are identical. Sometimes a manufacturer owns several brands. Sometimes a distributor supplies a private-label product made by another company. Supplier exports may use Brand, Manufacturer, Mfg, Maker or a value copied from a previous system.
The marketplace needs both questions to remain answerable:
- What name helps the buyer recognise and compare this item?
- Which manufacturer should procurement aggregate, audit or use for equivalent-product analysis?
A generic specifications object can store the words, but it cannot guarantee consistent identity. Acme, ACME® and Acme Corporation become separate facet values. An import may overwrite a curated brand when it intended to update the manufacturer. Historical reports change when the product record is corrected.
The issue is not cosmetic taxonomy. It affects discovery, purchasing intelligence and the meaning of an order.
Make both identities optional and independent
The product can link to one active Brand and one active Manufacturer.
Neither relationship is required. A supplier may provide one, both or neither. The import does not infer a missing brand from the manufacturer or a missing manufacturer from the brand.
That restraint matters. Guessing fills more cells but reduces truth. If a marketplace later learns that a private-label brand is manufactured by a different organisation, the model can represent the correction without undoing a collapsed field.
Independence also means a product may legitimately link to canonical Brand Acme and canonical Manufacturer Acme. The records answer different questions even when their display names match.
This is a useful modelling rule: cardinality and semantics should follow the business dimension, not today's coincidence of values.
Give each domain a canonical name and aliases
Both modules follow the same relational pattern.
A canonical record stores a display name, normalized name, handle and optional external identifier. Alias records store known source variations and the context that introduced them.
Active normalized names and handles are unique inside each domain. Normalized aliases are unique as well. When the import receives a known variation, it can resolve the canonical identity rather than create another filter value.
For example, trademark characters, casing and harmless presentation differences can normalize to the same known entity. An alias makes an intentional equivalence durable.
This is not fuzzy matching. The platform does not decide that two similar corporate names must be the same. It records known alternatives and protects their uniqueness.
Brand aliases remain in the Brand domain. Manufacturer aliases remain in the Manufacturer domain. Sharing the pattern does not merge the identities.
Why two similar tables are not duplicate architecture
At first glance, Brand and Manufacturer look like the same feature twice. Both have a name, a handle, aliases and a relationship to products. It is tempting to save effort by creating one generic “organisation” table with a type column.
That would make the database shorter, but it would blur the product language again. The two domains have different ownership policies, different search meanings and different historical questions. A merchant may curate the brand buyers see while accepting manufacturer data from a supplier. A brand merge should not accidentally rewrite a manufacturer facet. A report grouped by manufacturer should never depend on whether somebody classified the same record as a brand last week.
We reused the relational pattern and the implementation approach, not the business identity. This is an important distinction when extending Medusa: reuse the mechanism where it reduces engineering cost, while keeping separate concepts where the business needs separate answers.
It also leaves room for the domains to evolve independently. Brand may later carry merchandising content and storefront imagery. Manufacturer may carry compliance identifiers or procurement metadata. Neither roadmap has to distort the other.
Stop treating identity as a generic product attribute
Supplier specifications still contain valuable facts: material, dimensions, capacity, colour, voltage and unit of measure.
Brand and Manufacturer are different. They are reused across products, indexed as facets, updated through their own policy and carried into purchase history.
The import attribute mapper therefore recognises Brand, Manufacturer and Mfg as identity keys and excludes them from generic attribute creation. Dedicated synchronisation functions resolve or create the canonical record and maintain the product link.
That prevents the same incoming field from producing both a Manufacturer relation and a stray Manufacturer text attribute.
The live catalogue has one source of truth for each identity. Runtime consumers use the canonical relations instead of searching metadata and specifications for whichever legacy key happens to exist.
Let suppliers update only the identity they own
Recurring feeds do not automatically control every product field.
The update route captures a field-policy allow-list. Brand and Manufacturer are separate entries in that policy. A supplier feed authorised to change manufacturer does not implicitly receive authority over brand.
During reconciliation, the current side reads the canonical brand and manufacturer relationships. The incoming side reads the separately mapped source fields. The diff can show one changing while the other remains stable.
On confirmation, dedicated synchronisers apply only the allowed identity updates. Empty values follow explicit clearing policy rather than generic metadata merging.
This makes governance visible. The marketplace can curate Brand centrally while accepting Manufacturer from a trusted supplier feed, or the reverse, without custom branches in every import.
The data model enables the product policy rather than forcing all identity changes through one ambiguous column.
Give search two reliable facets
Elasticsearch is a projection of the Medusa catalogue, not an independent identity store.
The product-document query joins the canonical Brand and Manufacturer relationships and emits their IDs and names into separate fields. Search filters and aggregations can therefore answer different buyer and procurement intents.
A buyer can filter by the brand printed on the product. A procurement analyst can compare spending or alternatives by manufacturer. AI-assisted search can use both concepts without asking a model to reinterpret raw specifications on every request.
Normalization also improves the facet experience. Known variations resolve before projection, so Acme, ACME® and an approved alias do not fragment the result count.
Search remains downstream. Correcting a canonical identity in Medusa gives the indexing pipeline one authoritative change to project.
Snapshot what was purchased
The live catalogue evolves.
A product can be rebranded. A manufacturer relationship can be corrected. Two canonical records can be reconciled during a migration. None of those changes should rewrite the meaning of an order placed last year.
When an order is placed, the platform captures product dimensions for each order line. The snapshot stores Brand and Manufacturer independently alongside product title, SKU and other purchasing facts.
Purchase-history and accounting queries prefer that order-time snapshot. For older rows created before the snapshot capability, they can fall back to the current catalogue relation, but current values do not replace evidence that was captured at purchase time.
This distinction lets the business answer two valid questions:
- What is the product called now?
- What brand and manufacturer were associated with the item we bought then?
Commerce history deserves event-time meaning.
Use the purchased dimensions beyond reporting
The snapshot is useful across several operational surfaces.
Purchase-history analytics can group by Brand or Manufacturer. Invoice and document templates can display the recorded product identity. Accounting exports can use the purchased manufacturer instead of looking up a mutable product. Equivalent-product analysis can distinguish a buyer's preferred brand from the underlying manufacturer.
These capabilities share one benefit: they do not need to parse supplier metadata independently.
The identity contract begins at import, becomes canonical on the product, projects into search and freezes on the order line. Each stage uses the representation appropriate to its lifecycle.
That continuity is what makes the data useful rather than merely tidy.
Migrate legacy values once, then remove ambiguity
The project had historical identity values in attributes and metadata.
A versioned migration examined canonical fields, old attributes and recognised specification keys. It normalized candidates, identified conflicts, populated the two canonical domains and their product links, and updated order snapshots where evidence allowed.
The migration then verified the cutover and removed the legacy runtime dependency. The accepted architecture does not keep a reconciliation cron that continually guesses across canonical relations and arbitrary metadata.
This one-way boundary matters. A permanent fallback would let new inconsistencies accumulate and make every read path responsible for precedence. After migration, runtime code trusts the canonical relations; legacy resolution remains migration logic.
The public lesson is not the SQL. It is that canonicalisation needs an end state.
Do not hide conflicts behind precedence
Legacy sources can disagree.
A canonical field may say one manufacturer while a specification says another. Choosing the first non-empty value can complete a migration, but it can also conceal a catalogue-quality issue.
The resolution helpers collect candidates and identify normalized conflicts relative to the selected value. That gives the migration and its verification a way to distinguish harmless duplicates from contradictory evidence.
The same principle applies to new imports. Brand and Manufacturer arrive through explicit fields and policies. Generic specifications cannot silently override them.
When identity is consequential for search and purchasing history, disagreement should become a reviewable fact rather than an invisible priority rule.
A practical product-identity checklist
Before modelling Brand and Manufacturer, ask:
- Which buyer question does Brand answer?
- Which procurement question does Manufacturer answer?
- Are both optional?
- Can they have the same display name without becoming one record?
- Does each domain have a canonical normalized identity?
- Are known aliases explicit rather than fuzzy guesses?
- Do imports expose separate source fields?
- Are identity keys excluded from generic specifications?
- Can update policy authorise Brand and Manufacturer independently?
- Does the review diff read the canonical relationships?
- Does search project two separate facets?
- Are both identities captured when an order is placed?
- Do history queries prefer the purchased snapshot?
- Is there a bounded migration path for legacy metadata?
- Does runtime stop reading legacy identity after cutover?
If one text field has to answer all fifteen questions, the model is carrying too much ambiguity.
The broader lesson
Medusa gives us an extensible product model and durable order lifecycle. The client's catalogue needed two product identities that Medusa did not prescribe automatically.
We added them as first-class domains rather than copying supplier text into metadata. Separate canonical records preserve semantics. Aliases control known variations. Import policies govern authority. Elasticsearch gives buyers and procurement distinct facets. Order-line snapshots preserve what was purchased.
The value is not that the schema looks cleaner. The marketplace can now answer the right question with the right identity at every stage.
When Brand and Manufacturer happen to match, the model remains simple. When they diverge, the business does not have to rebuild its catalogue to tell the truth.
