Skip to content

Integrations · Catalogue changes

Your edit, and the minutes after it.

Most apps that read a catalogue copy it overnight. That is cheap to build and it is why an assistant can confidently describe a product you discontinued last Tuesday. Refik is told when a product changes and reprocesses that product instead of the catalogue, which removes the stale-copy problem and introduces a smaller one in its place: a short, measured delay. This page is that whole path, including the delay, because an assistant that answers from your catalogue is only as honest as its description of when it last looked.

Status Working today Two webhook subjects, one route Back to the full list

Two subjects

Updates and deletions are separate subscriptions, and the second one is not optional.

An update notice fires for a product that still exists. It does not fire for one you deleted, which sounds obvious and is exactly where this goes wrong if you only subscribe to updates: the deleted product stays in the knowledge Refik answers from until the next full rebuild, and the assistant keeps recommending something a shopper cannot buy. Sending a shopper to a product that no longer exists is worse than saying nothing, so deletion is subscribed on its own and both subjects arrive on the same route.

Subject one

A product was edited

Price, title, description, status, variants, anything. The notice carries both a numeric identifier and the global one; Refik keeps the global one because that is the form its own records already use, and the numeric form would have to be translated on every read.

Subject two

A product was deleted

Here only the numeric identifier arrives, which is part of why the two subjects cannot be collapsed into one assumption about the shape of the payload.

Which of the two happened is never read from the notice’s subject header. That header sits outside the signature, so trusting it would mean letting an unsigned string decide whether a product gets removed.

Instead the decision is taken from the one place that cannot be spoofed: the answer Shopify’s own API gives when the product is asked for again, filtered to products that are actually active. A product that comes back missing is removed; a product that comes back is rewritten from what Shopify says about it now.

Two stages

A cheap accept, then the actual work on a schedule.

Shopify expects a webhook to be answered in seconds and resends anything that is not accepted. Doing the real work inside that window would mean calling the admin API, reparsing the knowledge base and rewriting it before replying — slow on a good day and a retry storm on a bad one. So the request path writes one row and returns, and the work happens later.

Stage one: the notice arrives

Signature checked, store recognised, one indexed row written, accepted. No admin call, no cache write, no parsing. The row is not a copy of the product — it is a note saying look at this identifier in this store, and none of the product fields in the notice are kept.

That last detail is the security-relevant one. The store name arrives in a header that sits outside the signature, so it is treated as an address rather than as evidence: the truth about the product is read later from that store’s own API with that store’s own credentials. A misaddressed note can at worst ask one store about an identifier it does not have, which returns nothing.

Stage two: the hourly run

Once an hour the accumulated rows are processed together: the changed products are fetched, only those records are replaced, and the envelope is rewritten once rather than once per product.

A run handles up to 250 products, so a very large edit finishes across consecutive runs instead of being dropped or attempted all at once.

A store that has never been set up cannot create rows at all: if there is no knowledge base for it the notice is refused and nothing is written, so an unrecognised store cannot fill the queue.

Interface illustration, drawn from this page’s own two stages — the request path writes one row and returns, and the work happens on the scheduled run that the dashed line marks. The left box carries what the section says stage one does, and what it says stage one does not; the right box carries what the run replaces. The delay this buys, and its ceiling, are stated in the next section rather than drawn here, and the run’s own limits are the figures above with their sources.

Why a queue at all

The bulk edit is the case that decides the design.

Change the price on 500 products and Shopify sends that many notices in seconds. Rewriting the knowledge base on each one would mean two cache writes every time and as many reparses of the same large document — on the smallest storage tier underneath, that is a full day’s quota spent on one edit. The queue turns the same work into one database upsert per product, collapsed so that a product changed ten times is still one row, plus a small fixed number of cache writes per run.

Naive

1,000 writes

Two cache writes per notice, once for every notice that arrives.

Queued

4 writes

The same products split across consecutive runs, two writes each.

Collapsed

One row

The same product edited repeatedly is one pending row, not a backlog.

Cost

The delay

Paid for in time rather than in dropped notices.

The delay, stated

Not real time, and here is the number.

A change shows up to a shopper at the next hourly run, plus up to 60 seconds of caching on top. That is the whole answer, and it is worth being blunt about the implication rather than burying it: Refik is not the right place to read a flash-sale price or a stock level that is changing minute by minute. The product page is, and Refik points shoppers at it rather than competing with it.

What the delay does not affect

Availability shown on a storefront block is checked against Shopify at render rather than read from the cached knowledge, so the routine suggestion does not offer something that went out of stock half an hour ago. The delay is about the descriptive knowledge Refik answers from, not about the live checks that sit in front of what a shopper is shown.

The block that re-checks stock before it renders

Why the number is a ceiling and not an average

An edit made just before a run is picked up almost immediately; one made just after waits the better part of an hour. We publish the ceiling because the average is the figure that flatters us and the ceiling is the one you would plan around.

We have not measured how this behaves on a store with a very large catalogue under sustained editing, and this page does not guess at it. That is a gap rather than a reassurance.

What a full rebuild is for

The incremental path exists so that the full rebuild is rare. A full pass costs dozens of admin requests and real model spend per store, which is fine once at setup and wasteful on every price change.

The setup page describes what the first pass reads and what it writes back.

What setup touches

The limits of this page

A notice arriving is not the same as a notice being sent.

Shopify decides when to send these notices and whether to resend. Refik can only describe what it does with what arrives, and a notice that never arrives leaves a record slightly older than your catalogue until the next full pass. There is no second channel watching for that today, and no page here claims there is.

What this page does not cover: inventory as a separate subject, collections, metafields other than the one the routine block reads, and anything about how often the catalogue is rebuilt from scratch on an established store. Those are either not subscribed or not measured, and the difference between the two is the kind of thing this site tries not to blur.