Product availability changes are one of the easiest ways for a WooCommerce search experience to become misleading. A product can be deleted from WooCommerce, hidden from the catalog, or temporarily out of stock while its vector remains in Weaviate. If those states are not synchronized, shoppers may receive recommendations for products they cannot buy.
For agencies, the solution is to treat the vector index as a synchronized search projection rather than a permanent product archive. Every indexed object needs enough state to determine whether it is eligible to appear in a particular WooCommerce experience.
Model availability as indexed data
A Weaviate product object should normally include identifiers and availability fields alongside the text used to generate its vector. A practical schema might include:
product_id: The WooCommerce product ID.sku: The product SKU, when available.stock_status: For example,instock,outofstock, oronbackorder.catalog_visibility: The WooCommerce catalog visibility value.is_deleted: A synchronization flag indicating that the source product no longer exists or should no longer be indexed.updated_at: The source modification time or synchronization timestamp.
Keep these fields separate from the descriptive content. A product may remain semantically useful for analytics or internal merchandising even when it should be excluded from customer-facing search.
Choose between hard deletes and soft deletes
A hard delete removes the Weaviate object. It is appropriate when the product must not be retained for any purpose, such as when a merchant permanently removes a product and has no reporting or audit requirement for it.
A soft delete updates the object with a state such as is_deleted: true. This is useful when synchronization jobs can fail temporarily, when deletion events may arrive out of order, or when an agency needs an audit trail. Customer-facing queries must always filter out soft-deleted objects.
A common operational policy is to soft-delete immediately and hard-delete during a scheduled cleanup after a retention period. That approach reduces the risk of accidentally losing recoverable data while preventing the collection from accumulating obsolete objects indefinitely.
Filter unavailable products at query time
Do not rely only on an application-side check after Weaviate returns results. If unavailable products are retrieved first and removed later, the result set may contain too few products, and the ranking context may be less useful. Apply availability filters to the Weaviate query itself.
With the Weaviate Python client, a filtered query can look like this:
from weaviate.classes.query import Filter
products = products_collection.query.near_text(
query="lightweight waterproof hiking jacket",
filters=(
Filter.by_property("is_deleted").equal(False)
& Filter.by_property("stock_status").contains_any(
["instock", "onbackorder"]
)
),
limit=12,
)
The exact stock policy depends on the store. Some merchants want only products that can ship immediately, in which case the filter should allow only instock. Others want backorders and preorders included, provided the user interface labels them accurately.
If the collection uses a boolean such as is_available, the query can be simpler. However, that value must be updated whenever stock, catalog visibility, purchasing restrictions, or deletion state changes.
Do not confuse stock status with product deletion
An out-of-stock product is not necessarily deleted. It may return to stock, retain reviews and sales history, or remain useful in “similar products” results. A deleted product, by contrast, should normally be excluded from customer-facing recommendations and search regardless of its previous stock state.
Use separate fields and separate business rules:
- Out of stock: Keep the object if the merchant wants it searchable, but filter or rank it according to the store’s availability policy.
- Private or hidden: Exclude it from public queries while retaining it for authenticated staff workflows if required.
- Deleted: Mark it as deleted immediately and remove it from all public query paths.
- Discontinued: Decide whether it should remain available for historical reporting, replacement recommendations, or neither.
Synchronize changes with idempotent updates
WooCommerce integrations commonly receive changes through webhooks, scheduled imports, or polling jobs. Whichever mechanism is used, the update operation should be idempotent. Processing the same stock or deletion event twice should produce the same Weaviate state.
Store a stable WooCommerce product ID as the object identity or as a unique property used by the synchronization layer. When an event arrives, compare its source timestamp or version with the indexed updated_at value. This prevents an older webhook from changing a product back to an obsolete state.
A deletion handler should update the state before attempting cleanup:
product = products_collection.data.update(
uuid=weaviate_uuid,
properties={
"is_deleted": True,
"deleted_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z",
},
)
The timestamp in production should come from the source event or synchronization process, not from a hard-coded value. If the object may not exist, the handler should treat a missing object as an expected condition and record it for reconciliation rather than failing the entire queue.
Handle updates to variations carefully
Variable products introduce an additional failure mode. The parent product may remain published while every variation is out of stock, or one variation may be available while the others are not. Decide whether the vector index stores parent products, individual variations, or both.
For parent-level search, calculate an aggregate availability value from the variations. For example, a parent can be considered available when at least one purchasable variation is in stock. For variation-level search, index each variation with its own SKU, attributes, price, and stock state, then apply filters at the variation level.
When a variation affects the parent’s searchable text or availability, update both records in the same synchronization workflow. Otherwise, search may show a parent product that appears purchasable even though no matching variation can be selected.
Use batch operations for cleanup
Large stores should not issue one network request per deleted product during a cleanup. Mark objects as deleted as events arrive, then periodically identify stale objects and process them in batches. Batch deletion reduces request overhead and makes the job easier to retry.
Before hard-deleting, verify that the object is still marked as deleted and that its deleted_at value is older than the retention threshold. This protects against deleting a product that was removed and then restored while the cleanup job was running.
Also distinguish between deleting by object UUID and deleting by a property filter. Property-based deletion can be convenient for maintenance tasks, but a narrowly scoped set of UUIDs is generally safer when the cleanup process has already determined the exact objects to remove.
Plan for stale events and missed webhooks
Webhooks are useful for low-latency updates, but they should not be the only consistency mechanism. Network errors, duplicate events, disabled hooks, and temporary API failures can leave stale products in Weaviate.
Use a reconciliation job that periodically retrieves WooCommerce products changed since the last successful checkpoint and compares their state with the corresponding Weaviate objects. A second job can scan indexed records that have not been confirmed recently. The reconciliation process should be resumable and should record failures by product ID.
Useful monitoring metrics include:
- The number of public search results excluded because they were unavailable.
- The age of the oldest unprocessed synchronization event.
- The count of Weaviate objects marked deleted but not yet hard-deleted.
- The number of indexed products with no matching WooCommerce record.
- The percentage of indexed products whose availability timestamp exceeds the synchronization service-level objective.
Test the customer-facing behavior
Availability logic should be tested as an end-to-end feature, not only as a database update. At minimum, test that a product disappears from public search after deletion, that an out-of-stock product follows the store’s configured policy, and that a restored product becomes searchable again without creating a duplicate object.
Also test simultaneous events, such as an out-of-stock update followed by a deletion, and the reverse order. Verify that stale events cannot overwrite newer state. For recommendation systems, test whether unavailable products are filtered before the final result list is assembled and whether enough eligible alternatives remain.
For agencies managing several stores, make availability policy configurable per site. One merchant may permit backorders in search, while another may require immediate availability. The Weaviate data model can remain consistent while the query filters and ranking rules vary by storefront.