Inventory Badge Architecture: 48 Calls per Category Page
Northwind Outfitters runs SuiteCommerce Advanced on a single NetSuite account. Its 12,000 active SKUs are stocked across six warehouses, and a WMS pushes inventory levels to NetSuite every 10 minutes. Product list pages show 48 items, each with an 'In stock at your store' badge. The current implementation issues one jQuery AJAX call per product card to a custom Suitelet that reads inventory; median response is 2.8 seconds, p95 is 5.5 seconds, and a 48-item page generates 48 script calls. The CDN hit ratio for those calls is 11%, and NetSuite concurrency alarms fire during promotions. Merchandising wants badges to remain visible during flash sales, and store associates need a confidence indicator when data is older than 30 minutes. The team has three weeks and cannot change the ERP or add an external database. A developer proposes caching the Suitelet response for 24 hours to cut load.
1. Diagnose the architectural fault in the current badge implementation and evaluate the 24-hour cache proposal. Where should the caching boundary sit?
Read the worked answer
Diagnosis. The implementation is a chatty N+1 pattern: one browser-initiated Suitelet invocation per product card. Each invocation consumes its own governance and concurrency budget, so a 48-item page creates 48 server-side requests at the same moment. Latency compounds because the browser opens a limited number of connections and the main thread processes 48 callbacks. The 11% CDN hit ratio confirms that these responses are being treated as dynamic and largely uncacheable.
Why 24 hours is unsafe. Inventory is a perishable fact. A 24-hour cache would show stock that no longer exists, hide stock added for a flash sale, and make the requested 'data older than 30 minutes' confidence indicator meaningless. A long TTL also creates an oversell risk if the badge influences checkout decisions. The proposal treats the symptom (load) rather than the cause (per-card requests).
Where to cache. Cache a server-side availability snapshot, not the HTTP response, and key it by SKU plus location. The TTL should be no longer than the WMS feed interval plus a small buffer, for example 10 to 15 minutes, with an explicit asOf timestamp returned to the client. Shared caching is appropriate only for anonymous, non-contract availability. Customer-specific or contract inventory must bypass shared caches because the answer depends on the account. A 24-hour edge cache is therefore both stale and potentially wrong for logged-in users.
2. Design the batch endpoint and data flow from the WMS feed to the badge. Address governance, staleness, and failure behavior.
Read the worked answer
Data flow. A scheduled SuiteScript, running every 5 to 10 minutes, reads the current inventory snapshot with a saved search and writes a compact custom record keyed by SKU and location. Store only what the badge needs: quantity bucket (in stock, low, out), asOf, and feed status. Do not load full item records in this path. The scheduled script owns the expensive join once, not 48 times.
Endpoint. Expose one SSP service endpoint or Suitelet that accepts a store identifier and an array of SKUs, then performs a single search using an IN filter over the custom record. Return a JSON map of SKU to status plus a top-level asOf and feedStatus. This reduces 48 script invocations to one and avoids per-row record loads. Cap the array size, for example 100 SKUs, and reject oversized payloads rather than silently truncating them.
Client behavior. Make one request after the initial product markup renders. If the shopper changes store, abort the in-flight request and refetch for the new store; otherwise a late response can paint badges for the wrong location. Render a skeleton state first so the page is not blocked.
Staleness and failure. If asOf is older than 30 minutes, return the last known status with a stale: true flag so the UI can display a confidence note. If the feed has failed or the endpoint times out, return unknown per SKU rather than unavailable; false unavailability is worse than an honest 'check in store'. The endpoint should return a structured partial result, not a 500 that blanks the whole grid.
3. Define acceptance criteria and a rollback-safe rollout plan for the three-week window.
Read the worked answer
Acceptance criteria. Measure before and after on the same category page and device profile. Targets: one availability request per page load instead of 48; server p95 for the batch endpoint under 800 ms; no NetSuite concurrency alarms during a controlled promotion test; badge status matching a manual WMS sample of at least 100 SKUs across three stores; and the stale indicator appearing when the feed timestamp exceeds 30 minutes. Track LCP and main-thread blocking time as secondary outcomes, because the batch call should remove 47 network round trips and 47 callbacks.
Rollout. Put the new endpoint behind an extension-level feature flag and enable it for one low-traffic store first. Compare its badge output against the old path for 48 hours. Keep the old Suitelet deployed but unreferenced during the comparison so rollback is a configuration change, not a redeploy. Publish the custom record and scheduled script first, verify the snapshot is populating, then deploy the client extension.
Rollback. If accuracy or latency regresses, disable the extension and revert to the previous badge behavior while leaving the snapshot job running for diagnosis. Do not roll back by deleting the custom record, because that destroys the evidence needed to explain bad badges. Instrument error counts, unknown rates, and feed age so the team can see whether a rollback is warranted before customers report it.