Keep the in-stock filter aligned with inventory updates
Trace inventory from its authoritative source into search and storefront projections so the in-stock filter does not contradict product availability.
In this guide
Available on the product page, absent from the filter
A replenished product shows stock on its detail page, but disappears when a buyer selects 'In stock' on the category page. Both screens may be reading valid data from different moments. The product page can use a fresh inventory response while search still carries an older stock projection.
Begin with a timeline rather than a cache purge. Identify when the source quantity changed, when Znode received it, when the product projection was updated, and when the search result was generated. Without that sequence, a refresh can hide the symptom while leaving the same inconsistency ready to return.
Define what in stock means
Available inventory is not always a single quantity greater than zero. Store, warehouse, reservations, safety stock, backorder policy, and product type may influence the decision. Determine which rules the existing implementation uses and which system owns each input.
Use the same business definition for the filter and the availability message, or explain their deliberate difference. An 'available to order' filter can include backorderable items, while an 'available now' filter may not. A precise label prevents a technical projection from promising a fulfillment outcome it cannot establish.
Compare scoped inventory observations
InventoryProjectionCheck.cs accepts observations from the source, synchronized inventory, published data, and search. It rejects mixed Store/SKU context, distinguishes unknown quantities, identifies stale observations, and reports disagreement between known availability states.
Populate the model using your verified inventory readers. Znode 9 maintains product inventory by warehouse; resolve the relevant warehouse policy before comparing the stages. This helper uses Available greater than zero as the synthetic fixture's policy. Replace that projection deliberately when reservations, backorders, or safety stock change your definition.
Inventory/InventoryProjectionCheck.cs csharp
using System;
using System.Collections.Generic;
using System.Linq;
namespace Gcg.DeveloperExamples.Inventory
{
public sealed class StockObservation
{
public string Stage { get; set; }
public int StoreId { get; set; }
public string Sku { get; set; }
public decimal? Available { get; set; }
public DateTimeOffset ObservedAt { get; set; }
}
public static class InventoryProjectionCheck
{
public static string[] Compare(IEnumerable<StockObservation> observations,
int storeId, string sku, TimeSpan maximumAge,
DateTimeOffset now)
{
if (storeId <= 0 || string.IsNullOrWhiteSpace(sku) || maximumAge < TimeSpan.Zero)
throw new ArgumentException("A valid scoped observation is required.");
var rows = observations.ToArray();
var findings = new List<string>();
foreach (var row in rows)
{
if (row.StoreId != storeId || row.Sku != sku)
throw new InvalidOperationException("Mixed inventory context.");
if (!row.Available.HasValue) findings.Add(row.Stage + ": unknown inventory");
if (now - row.ObservedAt > maximumAge)
findings.Add(row.Stage + ": stale observation");
}
var known = rows.Where(x => x.Available.HasValue)
.Select(x => x.Available.Value > 0).Distinct().Count();
if (known > 1) findings.Add("Availability projections disagree.");
return findings.ToArray();
}
}
}
// Populate each observation from one verified source, synchronization, or search read.
// This fixture's in-stock definition is Available > 0; map your actual policy first.
Handle incomplete synchronization deliberately
A batch inventory response can contain some requested products but omit others. Decide whether omissions mean unknown, unavailable, or eligible for a bounded fallback. Do not silently convert every missing row to zero if the source contract does not define that meaning.
If fallback uses a live provider, bound its work and avoid a separate remote call for every product in a large result set. Measure the actual request path before optimizing it. A change that improves filter freshness can still create unacceptable dependency load if it replaces one projection read with hundreds of external requests.
Verify transitions and recovery
Test replenishment and depletion separately. Include two stores or warehouses when stock is scoped that way, and use quantities that make incorrect sharing obvious. Check the unfiltered listing, filtered results, product detail, and cart validation. Agreement between two pages does not prove that checkout enforces the same policy.
Pause synchronization, fail a publication step, and return an incomplete inventory response. The system should expose an operationally understandable delay or failure. After recovery, confirm that every affected projection converges without manually changing the product record. Capture each stage's source timestamp so the recovery path can be traced.
- Distinguish missing data from known zero inventory.
- Check cache keys for store and inventory context.
- Record freshness lag before promising a response-time improvement.
Operate the freshness budget
Agree an acceptable lag between source changes and search availability. Monitor that lag independently from raw API response time. A fast search response containing yesterday's inventory is not a healthy result for a buyer who needs a part today.
The goal is a clear inventory story across the storefront. Once the source definition, projection sequence, and recovery behavior are known, developers can choose targeted updates or caching changes with evidence. Broad cache clearing becomes a diagnostic tool of last resort rather than the normal way the in-stock filter stays believable.
References and further reading
Bring your next engineering question.
Connect catalog and inventory workflows
Independent guidance from GCG. Znode is a trademark of its owner. Examples use fictional data and are not official platform documentation. Suggest a correction.