Field note

REST is not GraphQL. The difference is a missing dimension.

The argument is usually had about syntax, or about round trips. Both are real and both are the small version of it.

A row-based integration answers one question: what is this thing now. That was sufficient for as long as commerce was one store, one currency, one jurisdiction, and one customer record. It is no longer what anything asks.

Ten domains follow. They look unrelated — returns, consent, warehouse robotics — and they fail identically, because each one asks what was true, for whom, where, and when, and a current-state row has nowhere to put three of those four.

None of this is a criticism of the systems that hold current state. They were built correctly for the shape that existed. The shape changed.

01

Omni-tenant

Missing axis: tenant

Brands, regions, B2B, retail, and channel storefronts under one organisation. When the model has no tenant axis, a second storefront is not another row — it is another instance, with another contract line and another set of seats.

The tell is in the invoice rather than the architecture diagram: deduplication billed per seat, the same customer resolving differently in two systems, and the fifth market costing what the first four did. Spend scales with the number of copies rather than the amount of business.

02

Returns and RMA

Missing axis: time

A return is a retrospective question by definition. What was actually paid, in which currency, under which tax treatment, inside which market's withdrawal window, against which unit.

Every one of those is a point-in-time lookup, and a system that overwrites in place destroyed the answer at write time. The failure is not that returns are hard — it is that the data required to settle one was never retained, so the answer gets reconstructed from partial copies and defended rather than produced.

03

Omnibus

Missing axis: time × market

The EU price-indication rules require the lowest price applied in the preceding thirty days, in that market, shown alongside the reduction. That is not a calculation you can perform later. It requires having observed and kept the prices as they stood.

This is the clearest case of a defect you cannot remediate after the fact. A platform migration fixes the future; nothing recovers an observation nobody recorded. The earliest date any answer becomes possible is thirty days after logging begins — which makes starting the clock the whole intervention.

04

Consent

Missing axis: purpose × time

Consent Mode v2 asks for four separate signals — ad storage, analytics storage, ad user data, ad personalisation. Most customer systems still hold one boolean, because a boolean was sufficient when consent was a single yes.

Four purposes across seven storefronts is twenty-eight configurations before a single country, spread across a tag manager and a consent platform, drifting independently, and priced per tag. The deeper problem is that all of it is configuration, not record: it describes what should have happened, not what did. When the question is which consent applied to a specific buyer on a specific date, configuration cannot answer it.

05

Conversion and retargeting

Missing axis: consent state at event time

Server-side tagging and modelled conversions both assume the platform can state the basis on which an event was collected. If consent is a flag that has been overwritten twice since, the basis is unknowable, and the audience built from it inherits that.

Suppression is the visible half — a buyer who withdrew should stop being retargeted everywhere, not just where the flag happened to sync. The invisible half is worse: spend optimised against signals whose lawful basis cannot be reconstructed.

06

ISO codes and hreflang

Missing axes: market and locale, kept separate

Country, language, currency, and tax jurisdiction are four different things that a row-based catalogue tends to collapse into one field. Belgium takes two languages. German is priced differently in Germany, Austria, and Switzerland. English is not a market.

Collapse them and the symptoms are familiar and unconnected-looking: hreflang pointing at country when it annotates language, the wrong currency rendered for a correct locale, and duplicate-content signals across storefronts that were meant to be one offering seen from different places.

07

The browser

Missing axis: agreement between what is rendered and what is claimed

The rendered page is the offer. Not the ERP record, not the feed — what the buyer was shown. Structured markup on that page is a parallel claim about the same offer, and the two are generated by different systems on different schedules.

That inconsistency used to be invisible because checking every page was uneconomic. It no longer is. Whoever scans the storefront reads the page and the markup together, and disagreement between them is the first thing found.

08

Mobile and app surfaces

Missing axis: surface

A native surface cannot scrape a web page. It needs the same offer resolved for the same market, delivered as data — and if the resolution logic lives in the storefront's rendering layer rather than in the record, every new surface re-implements it.

Re-implementation is where surfaces disagree. Two clients, two interpretations of the same catalogue, and no way to say which was correct at the moment a buyer acted on it.

09

Connected devices

Missing axis: unit identity

A SKU identifies a model. A device is a unit, with its own firmware level, its own entitlement, and its own service history. Regulation increasingly addresses the unit — a product passport describes an item, not a product line, and vulnerability obligations attach to what is deployed.

A catalogue with no serial-level axis cannot say which units received which firmware, or revoke access for one device without revoking it for the model.

10

The robot in the warehouse

Missing axis: machine-resolvable identity

Automated handling reads an identifier and expects it to resolve, unambiguously, to the item in front of it — origin, hazard class, destination market, handling constraint. It cannot infer from a product page, and it will not ask for clarification.

This is the least forgiving consumer of the same data, and the most honest test of it. If the identifier resolves to a shape with market, unit, and time, automation works. If it resolves to a human-readable page, someone is standing at the line reconciling by hand — which is the same reconciliation problem as everything above, wearing a hi-vis vest.

One failure, ten costumes

Read the list again and the through-line is hard to miss. Tenant, time, purpose, market, unit, surface — each domain fails on a dimension the record does not carry, and each is patched locally with another instance, another tool, another copy that must be reconciled with the others.

That is the actual cost, and it does not appear as a line item. It appears as headcount reconciling, as per-seat deduplication, as a fifth country priced like a fifth business, and eventually as an obligation that cannot be met because the evidence was never kept.

The fix is not a faster transport. GraphQL alone does not help: a shaped query over a flat, current-state store returns flat current state, faster. What changes the outcome is a record that carries the dimensions — resolved per market, appended rather than overwritten, timestamped — with everything else reading from it.

Built on this

PIM Sync keeps that record for Shopify catalogues — market-resolved, appended, timestamped — beside whatever product master, feed manager, and marketplace connector you already run. It does not replace them. It answers the question they were never shaped to hold.

PIM Sync on the Shopify App Store ↗  ·  Migration guide: product.csv to Catalog and metaobjects ↗