At a glance
This card compares the number of product documents in your Elasticsearch search index against the number of active, sellable products in your ecommerce catalogue. When the two numbers drift apart, your product-sync pipeline into search has broken: shoppers can no longer find SKUs that exist in the store, or the index is serving stale products that no longer sell. For a platform team, this is the single clearest signal that “search is lying to customers about what we sell”. A drift of more than 100 documents trips the alert because at that scale the gap is structural (a failed reindex, a stuck connector, a mapping rejection) rather than the normal few-second lag of a healthy near-real-time index.
Calculation
The card computes a two-sided comparison:_count is preferred over _cat/indices ... docs.count deliberately. The _cat figure includes deleted documents that are still present in Lucene segments but not yet merged away, so it overstates the live, queryable population. _count returns only live documents, which is exactly the set a shopper’s search can return.
The alert fires on the absolute value: abs(drift) > 100. The card holds both the raw counts and the signed drift so the headline can show direction (for example “ES is short by 412 docs” versus “ES has 412 stale docs”). The 24-hour strip is sampled on each refresh so a step change pinpoints the moment a sync job failed.
If the product index is aliased (a common pattern where products is an alias pointing at products-v7), the card reads the count through the alias so a blue/green reindex swap does not register as spurious drift while both indices briefly co-exist.
Worked example
A homewares retailer runs Adobe Commerce as the catalogue of record and an Elasticsearch cluster (managed, 3 data nodes) as the storefront search backend. A nightly connector reindexes thecatalog_product index from Magento into the products alias in Elasticsearch. Snapshot taken on 14 Apr 26 at 08:10 BST, shortly after the overnight job ran.
The Vortex IQ headline shows -418 drift in red because it exceeds the 100-document threshold. Reading the 24-hour strip, the gap was zero at 02:00 (before the job) and stepped to -418 at 03:47, exactly when the reindex connector logged a batch failure. The platform team investigates in this order:
- Confirm the direction. Negative drift means missing SKUs, the worse of the two cases, because 418 live products cannot be found in storefront search at all. That is direct lost revenue, not a cosmetic issue.
- Find the failing batch. The connector log shows a bulk request rejected partway through with
mapper_parsing_exceptionon a newcolour_familyattribute that Adobe added but the Elasticsearch mapping does not know about. Every document in that batch (and every batch after the failure, if the job aborts) never landed. - Quantify the exposure. 418 of 48,930 products is 0.85% of the catalogue. If those products were a random slice they would carry roughly 0.85% of search-driven revenue, but in practice the missing batch is often a contiguous range (a newly imported supplier feed), so it can be disproportionately the newest, most-promoted products. The team cross-checks merchandising to see whether any are in an active campaign.
- A drift card is an early-warning system for sync failures that produce no error on the storefront. The site does not 500; search simply returns fewer results. Without this comparison the gap is invisible until a merchandiser or customer notices a specific product is “missing”.
- Positive drift is just as actionable as negative. If the next night the catalogue drops 600 discontinued lines but the delete-by-query never ran, ES would show +600 stale documents. Shoppers then find and click products that are out of catalogue, leading to dead PDPs and wasted ad spend.
- Resolve the root cause, not just the count. Replaying the failed batch fixes today’s drift, but the underlying mapping mismatch will recur on the next attribute Adobe adds. The durable fix is dynamic-mapping templates or a schema-change check in the connector.
Sibling cards
Reconciling against the source
Where to look in Elasticsearch and the storefront:Why our number may legitimately differ from a rawGET /<product-index>/_countis the authoritative live document count; this is the number the card uses on the Elasticsearch side. Run it through the alias if you use one.GET /_cat/indices/<product-index>?v&h=index,docs.count,docs.deletedshows live and deleted documents side by side; the difference explains why_catand_countdisagree.GET /<product-index>/_stats/docsgives the same live count plus per-shard breakdown, useful when drift maps to one shard. On the ecom side, reconcile against the platform’s own product count: Adobe Commerce admin product grid filtered to enabled/visible, BigCommerce Products count, or the Shopify products list filtered to active.
_cat/indices read:
Cross-connector reconciliation:
Known limitations / FAQs
Why does the card use_count instead of the number I see in _cat/indices?
_cat/indices reports docs.count including deleted documents still sitting in Lucene segments that have not been merged away yet. Those documents cannot be returned to a shopper, so counting them would understate real drift. _count returns only live, queryable documents, which is the population that matters for “can a customer find this product”.
A small drift appears and disappears within seconds. Is that a problem?
No. Elasticsearch is near-real-time: a newly indexed document is searchable and counted only after the next refresh (default once per second). During a steady-state sync you will see drift bounce by a handful of documents and self-correct. The alert is set at 100 precisely so this normal jitter never pages anyone. Investigate only sustained gaps.
The drift is positive (ES has more docs than the catalogue). What does that mean?
Stale or zombie products. Items were unpublished, archived, or deleted on the ecom side but the corresponding delete (or delete-by-query) never reached Elasticsearch. Shoppers can find and click these, landing on dead or misleading product pages. Fix the delete path in your sync, then run a one-off delete-by-query or full reindex to clear the backlog.
We use an alias for blue/green reindexing. Does that confuse the card?
No, the card reads the count through the alias. During a swap, where both the old and new index briefly serve the alias, Elasticsearch de-duplicates at the alias level for _count, so you will not see a spurious doubling. If you read the underlying indices directly you would, which is another reason the card prefers the alias.
Our catalogue legitimately differs from the index because we exclude some products from search. How do we stop false alerts?
Align the ecom-side count filter with what you actually index. If your storefront search deliberately omits, say, gift cards or B2B-only SKUs, configure the connector’s product scope to exclude the same set. Drift should be measured against the products you intend to make searchable, not the entire catalogue.
Can a non-green cluster cause apparent drift?
Yes. If a product shard is unassigned (red cluster) its documents drop out of the live _count, producing negative drift that is really an allocation problem, not a sync problem. Always check Cluster Status and Unassigned Shards before assuming the sync failed.
How fast should we react to a sustained negative drift?
Treat it like a partial outage of discoverability. The site is up, but a slice of the catalogue is invisible to search and therefore unsellable through that path. The cost grows linearly with time-open, and the fix (replay the failed batch, correct a mapping) is usually minutes once located. Sustained negative drift above the threshold warrants same-shift action.