Table of contents :

Handling Product Updates Without Rebuilding Everything

100-days-of-weaviate-014

Table of contents :

Product catalogs change constantly: prices move, inventory is replenished, descriptions are rewritten, and products are assigned to new categories. A WooCommerce integration should not treat every change as a reason to delete and recreate the entire catalog in Weaviate. The safer approach is to identify the changed product, update only the necessary properties, and refresh its vector only when the searchable content has changed.

Separate product changes by type

Not every WooCommerce update has the same search impact. Before writing synchronization code, classify fields into groups:

  • Searchable content: product name, description, short description, attributes, category names, and brand information.
  • Filtering data: price, stock status, sale status, category IDs, product type, and visibility.
  • Operational metadata: WooCommerce product ID, SKU, timestamps, image URLs, and synchronization status.

A stock quantity change usually requires a property update but does not change the product’s semantic meaning. A rewritten product description does. This distinction prevents unnecessary vector generation while keeping search results current.

Use a stable object identifier

Store each WooCommerce product under a deterministic identifier, or persist the Weaviate object ID alongside the WooCommerce ID. A stable identifier makes updates idempotent: the same webhook or scheduled import can be processed more than once without creating duplicate objects.

For example, an integration might use a UUID derived from the WooCommerce product ID, or maintain a mapping such as woocommerce_product_id → weaviate_object_id. Do not use a product name or SKU as the only identity unless your business rules guarantee that it can never change.

Patch the existing object

When only a few fields change, update the existing object instead of deleting and importing it again. With the Weaviate Python client, a collection-level update can modify selected properties:

products = client.collections.use("Product" products.update( object_id=weaviate_id, properties={ "price": 79.99, "stock_status": "instock", "updated_at": "2025-02-14T10:30:00Z" } )

The exact client syntax depends on the Weaviate client version, but the integration principle is the same: address one known object and send the changed fields. Keep the WooCommerce product ID in the object properties so that reconciliation jobs can locate records even if an external ID mapping is lost.

Know when a vector needs to change

A vector represents the content used to position an object in semantic search. If a product’s description, title, category text, or other vectorized fields changes, the existing vector may no longer represent the product accurately.

For fields such as stock status or price, a vector refresh is usually unnecessary. Those values are better handled with filters or ranking logic. For example, an agency may search semantically for “waterproof hiking boots” and apply a filter for products where stock_status = "instock" and price < 150.

When vectorized properties are updated, confirm how the configured Weaviate vectorizer handles object updates. In configurations with automatic vectorization, a property update can trigger vector regeneration. If vectors are supplied manually or multiple named vectors are configured, update the relevant vector explicitly and ensure that the new vector was generated from the same content-building rules used during the initial import.

Build one canonical text representation

Semantic consistency is easier to maintain when the integration creates the vector input from a single function. The same function should be used during full imports and product updates.

def searchable_text(product):
    return "\n".join(filter(None, [
        product["name"],
        product.get("short_description"),
        product.get("description"),
        product.get("brand"),
        " ".join(product.get("categories", [])),
        " ".join(product.get("attributes", [])),
    ]))

If the title or description changes, regenerate the text and vector from the new representation. Avoid appending the new text to the old text, which can leave deleted claims or outdated specifications embedded in the representation.

Process WooCommerce webhooks defensively

Webhooks are useful for low-latency updates, but they should not be your only consistency mechanism. Requests can be duplicated, delivered out of order, or fail before the Weaviate write completes.

  1. Receive the WooCommerce event and record its product ID and event timestamp.
  2. Fetch the current product from WooCommerce rather than trusting a partial webhook payload.
  3. Compare the product’s relevant version or modified timestamp with the last synchronized value.
  4. Apply a property patch and regenerate the vector only if vectorized content changed.
  5. Record the successful synchronization timestamp and response status.

Use a queue for retries and make the worker idempotent. A periodic reconciliation job should also compare WooCommerce products with Weaviate records and repair missed updates.

Use batch updates for imports and backfills

For a large catalog change, do not issue thousands of independent network requests if the client and deployment support batching. Group updates into bounded batches, monitor failures, and retry only the objects that failed. Small batches make it easier to control memory use, avoid request timeouts, and respect resource limits during embedding generation.

Batching should not mean rebuilding everything. A nightly price synchronization might update only price-related properties for products whose prices changed. A description migration might select only products affected by the content rule and regenerate vectors for that subset.

Handle deleted and unpublished products explicitly

Product updates are only one part of catalog synchronization. When a product is permanently deleted, remove its Weaviate object. When it is private, out of stock, or excluded from search, either delete it or retain it with a property such as is_searchable and apply that property as a query filter.

Choose one policy and apply it consistently. Retaining hidden products can be useful for restoring visibility quickly, while deletion reduces index size and prevents accidental exposure if a filter is omitted.

Test update behavior before production rollout

Create an integration test that performs the complete lifecycle:

  • Import a product and verify its object identifier.
  • Change only its price and confirm that the filterable data changes.
  • Change its description and confirm that the searchable representation and vector are refreshed.
  • Send the same event twice and confirm that no duplicate object is created.
  • Process an older event after a newer event and confirm that stale data is not written.
  • Remove or hide the product and confirm that it no longer appears in storefront search.

Also inspect object counts and synchronization error logs after deployment. A stable object count, a low retry rate, and current modification timestamps are practical indicators that incremental updates are working as intended.

Trending posts
You might also like