- A buyer searches for a replacement part, finds the perfect result and opens the product page.
- The item belongs to a supplier who cannot deliver to the buyer's property.
- The search engine found the words.
- That was the problem we had to solve for a multi-vendor procurement platform built on Medusa.
The client problem
A buyer searches for a replacement part, finds the perfect result and opens the product page. Then the promise falls apart.
The item belongs to a supplier who cannot deliver to the buyer's property. The price shown in search is not the price available to that organisation. The product is classified in the wrong branch of the catalogue. Or it has been unavailable long enough that it should no longer appear as a useful result.
The search engine found the words. It did not understand whether the product could actually be bought.
That was the problem we had to solve for a multi-vendor procurement platform built on Medusa. The product catalogue was only one part of the commercial truth. Supplier ownership, variants, price context, taxonomy, attributes, stock policy and delivery coverage lived across several modules and relationships.
We built one canonical Elasticsearch projection that brings those facts together. Medusa remains the commerce source of truth. Elasticsearch receives a read-optimised version detailed enough to make each result commercially useful.
A product result is a promise, not a database row
On a simple retail site, indexing a product title, description and image can appear sufficient. A user searches, chooses a result and lets the product page resolve the rest.
A procurement marketplace has a harder job.
The same catalogue may contain many suppliers, customer-specific price lists, thousands of variants and different delivery territories. A buyer may be shopping for a particular property. Search therefore has to answer more than “Does this text match?”
It must help answer:
- Is this the right product and variant?
- Who supplies it?
- Which category and specifications does it belong to?
- Which commercial price context is available?
- Can the supplier deliver it to this location?
- Is it still useful to show this product as available?
If those questions are postponed until checkout, search creates false confidence. Buyers spend time opening results that the platform should have filtered earlier.
Our goal was not to copy the whole database into Elasticsearch. It was to define the minimum complete commercial document that search needed.
Why the base Medusa product was not enough
Medusa gave us the right foundation: products, variants, prices, inventory and commerce lifecycle. The project then extended that foundation with marketplace suppliers, procurement taxonomy, organisation pricing and seller fulfilment rules.
Those extensions are exactly why Medusa was a good architectural choice. We could model the client's business instead of forcing every requirement into a generic product record.
But the flexibility creates an indexing question. When the source data is modular, what exactly is “the product” from the search engine's point of view?
It is not one row. It is a projection assembled from several sources.
The product supplies its identity and copy. Variants supply SKUs and physical characteristics. Price sets supply standard commercial values. Price lists can add contextual overrides. Categories supply hierarchy and lineage. Marketplace relations identify the seller. Attributes provide specifications. Stock policy determines whether persistent unavailability should affect visibility. Seller fulfilment topology determines where and how the item can be delivered.
Indexing only the base product would discard much of the information that makes the marketplace useful.
We defined one canonical product document
The first important decision was to stop treating Elasticsearch updates as a collection of unrelated payloads.
We created one canonical builder for the product document. Whether the platform rebuilds a batch during reconciliation or refreshes a few products after a business change, both paths use the same underlying query shape and the same document assembler.
That matters because two builders inevitably drift.
One path starts including a new price field while another forgets it. A live update orders variants differently from a complete reindex. A taxonomy fix reaches recently changed products but not the rest of the catalogue. Search behaviour then depends on how and when a document happened to be written.
With one builder, the contract is explicit. The same source facts produce the same search representation. Automated tests guard ordering, field semantics, geography and stock-state behaviour.
The index is still disposable. Its document shape is not casual.
Compose identity before optimising relevance
Before a search engine can rank a product, it must know which product it is describing.
Our projection carries the Medusa product identifier, name, description, handle, image, creation and source-update timestamps. It also preserves structured variants with their identifiers, SKUs, titles, dimensions and inventory settings.
We resisted collapsing the product into one arbitrary SKU. A procurement catalogue often uses variants to represent pack sizes, finishes or supplier-specific references. Keeping the structure allows the query layer and product experience to remain precise.
Brand and manufacturer are also treated as canonical identities. Supplier feeds frequently repeat them in metadata or free-form attributes with inconsistent spelling. The builder favours the governed relations, then excludes duplicate identity-like attributes from generic specifications.
This sounds like data hygiene, but it changes the buying experience. “Manufacturer,” “brand” and “supplier” are different questions. Treating them as interchangeable makes filters unreliable and teaches semantic search the wrong vocabulary.
Bring commercial price context close to search
Price is another reason a marketplace result cannot be a plain product record.
The projection includes the standard product price and can expose sanitised price-list override fields. That gives the search layer enough commercial context to filter or order results without reconstructing every price relationship during each query.
It does not make Elasticsearch the final pricing authority.
Checkout still owns the definitive commercial calculation for the current customer, currency, quantity and applicable rules. The index is a fast representation used to find plausible products. That distinction prevents search infrastructure from quietly becoming a second pricing engine.
For the buyer, the benefit is simple: the catalogue can become more relevant to the organisation before they open every product page. For the architecture, the rule is equally simple: project the price facts required for discovery, then revalidate the transaction in commerce.
Make taxonomy useful to humans and machines
A category name alone is rarely enough in a large procurement catalogue.
“Valves” may exist under plumbing, heating or industrial equipment. Search and navigation need the hierarchy that gives the term meaning.
The canonical document therefore includes category identifiers, ordered category names, lineage, descriptive lineage, depth, parent and leaf status. The ordering is deterministic so the same source state cannot produce a different primary category depending on query timing.
Specifications receive similar treatment. Governed product attributes become structured key-value pairs. Long-form details remain separate from filterable specifications. When useful characteristics can be extracted from product copy, they supplement the structured set only if a canonical attribute has not already supplied the same key.
The result supports several discovery modes from one projection: category navigation, attribute filters, lexical matching and semantic retrieval.
It also avoids a common catalogue mistake: asking the search engine to infer structure that the commerce platform already knows.
Follow the seller's real delivery topology
Delivery was the most project-specific part of the document.
In this marketplace, shipping profiles belonged to sellers. The valid path was not product to shipping profile. It was product to seller, seller to fulfilment profile, profile to shipping option, option to service zone and zone to geography.
That distinction is crucial. Following a superficially plausible but unused relationship would have indexed no deliverable zones at all. A regression test now protects the correct path.
The projection stores both broad deliverable zones and richer delivery-option entries. Each richer entry keeps the shipping option, fulfilment type, estimated time and geographic coverage together.
Why together? Imagine one supplier offers fast delivery in one region and slower delivery in another. If geography and delivery time are stored in separate arrays, a query can accidentally combine the first region with the second region's promise. A nested option prevents that cross-match.
Postal patterns are normalised into values that Elasticsearch can filter exactly. Broad patterns receive a size guard so one unusually large territory does not inflate every document without limit.
The buyer sees a product because the seller's actual fulfilment setup can serve the context—not because somebody copied a generic “ships nationally” flag into metadata.
Build semantic search from governed facts
Semantic search is only as trustworthy as the text it embeds.
If the semantic field contains only a supplier's title and description, relevance depends on the quality of that copy. If it indiscriminately concatenates every piece of metadata, it amplifies stale and contradictory labels.
Our semantic representation is assembled from governed fields: product title and description, canonical brand and manufacturer, category context and supplier name. Structured specifications remain available for exact filters.
This lets the platform combine complementary techniques.
Lexical search handles exact references and familiar terms. Filters enforce category, geography, supplier or price constraints. Semantic retrieval helps when the buyer describes a need rather than a catalogue label. All three operate on the same underlying commercial projection.
The search engine is not asked to invent the catalogue's truth. It is given a better version of that truth to retrieve.
Keep source time separate from index time
Every derived index eventually drifts unless the system can compare it with its source.
The document records when the Medusa product source was last updated separately from when Elasticsearch wrote the projection. That small distinction gives reconciliation a stable marker.
An indexing timestamp says, “We wrote this document at this time.” A source timestamp says, “This is the version of the commerce record represented by the document.” They answer different questions.
The next part of this architecture uses those markers to find missing, stale or deleted documents and repair them in batches. The important point here is that reconciliation was considered in the document contract from the beginning.
A search projection should be rebuildable, comparable and replaceable. Otherwise a convenient cache gradually becomes an ungoverned database.
What this changed for the client
The immediate improvement was not a more sophisticated search box. It was a more credible catalogue experience.
Each result could carry enough context to support the questions procurement buyers actually ask: what the product is, who supplies it, how it is classified, what commercial context is available, whether persistent stock state makes it useful and whether the supplier can serve the buyer's geography.
The architecture also created a stable foundation for later capabilities: marketplace filters, delivery-aware discovery, AI-assisted search, product comparison and operational reconciliation all consume the same governed projection.
This is where an extensible commerce engine earns its place. Medusa provided the commerce primitives. We added the client's marketplace and procurement rules, then projected the combined model into infrastructure designed for fast discovery.
We did not force Elasticsearch to become the commerce platform. We made it understand enough of the commerce platform to keep its promises.
A practical document-design checklist
Before indexing products from a modular commerce platform, answer these questions:
- Which source owns each product, seller, price, category, stock and delivery fact?
- What must a search result know to be commercially useful, not merely textually relevant?
- Do live updates and full reconciliation use the same canonical builder?
- Are variants, brands, manufacturers and suppliers kept as distinct identities?
- Is indexed pricing clearly separated from final checkout calculation?
- Does delivery coverage follow the relations actually used by the marketplace?
- Are geography and delivery promises co-located so filters cannot cross-match them?
- Is stock represented as an appropriate search signal rather than a fake inventory ledger?
- Does semantic text come from governed fields?
- Can the index compare its represented source version with current Medusa state?
Those decisions determine whether search becomes a dependable buying tool or an attractive list of false positives.
The broader lesson
The client did not ask us to “put Medusa into Elasticsearch.”
They needed buyers to find products that made sense inside a multi-vendor, location-aware procurement journey. Medusa's base product was necessary, but the answer also depended on supplier relationships, commercial context, taxonomy, marketplace stock policy and the seller's fulfilment topology.
We solved the problem by treating the Elasticsearch document as a deliberate business projection.
Medusa remains the source of commerce truth. The index is fast and disposable. But the projection between them is rich enough to express what a useful search result actually means.
That is the difference between search that matches words and search that helps somebody buy.
