Skip to content
HEAPBYTE

Integration · October 21, 2025

Write the data contract before you write the integration


Written by the HeapByte engineering team

One system of record per field

Before any code is written, produce a table with four columns: field name, owning system, update direction, and conflict rule. This sounds like paperwork and it is genuinely the single highest-leverage hour of any integration project, because most integration bugs we are called in to diagnose are ownership ambiguities that were never resolved on paper and only surfaced once two systems started writing to the same field independently.

Inventory is the classic example, but it is far from the only one. Customer email addresses, order status, tax-exempt flags and loyalty point balances all commonly have more than one system with an opinion about the current value, and if the integration was built without a written answer to ‘who wins’, the answer in production ends up being ‘whichever system wrote last’, which is not a policy anyone chose deliberately.

The exercise also surfaces fields that nobody actually needs synced at all — data that looked important in a discovery workshop but that no downstream process actually consumes. Removing those from scope before building anything is one of the most reliable ways to cut an integration timeline.

Assume events go missing

Webhooks, including Shopify’s, are delivered at-least-once, which in practice also means sometimes zero times during an outage or a misconfiguration, and sometimes more than once during retries. Handlers must therefore be idempotent regardless of how reliable the delivery mechanism claims to be, processing must respect ordering where order genuinely matters — an order-paid event arriving before order-created will break naive handlers — and any gaps need a replay mechanism rather than a manual data-fix ritual.

Idempotency is not free; it typically requires storing a processed-event ledger keyed on the webhook’s unique ID and checking against it before acting, which is a small amount of extra infrastructure that pays for itself the first time a retry storm hits during a platform incident.

  • Idempotency keys checked on every handler before any write occurs
  • A dead-letter queue with alerting, not a silent log line, for events that fail processing
  • Scheduled reconciliation jobs that compare both systems and report drift, run on a cadence independent of the event stream

Make the sync observable

Queue depth, failure rate and reconciliation delta belong on a dashboard someone on the team actually looks at regularly, not buried in a logging platform that only gets opened when something has already broken. An integration nobody can inspect at a glance is an integration nobody can trust, and teams that cannot trust their integration end up doing manual spot-checks that defeat the purpose of automating the sync in the first place.

We generally recommend three numbers as a minimum viable dashboard: the current queue depth, the failure rate over the last hour, and the reconciliation drift from the most recent scheduled run. If all three are healthy, the integration is almost certainly fine; if any one of them moves, it is usually the earliest possible signal of a problem that would otherwise surface as a support ticket days later.

Where the contract earns its keep at renewal time

A written data contract also matters well beyond the initial build, because ERP and CRM vendors change their APIs, and Shopify itself deprecates and introduces webhook topics over time. When that happens, a team with a documented contract can assess the impact of a breaking change in an afternoon by checking which fields and directions are affected; a team without one has to reverse-engineer the current behaviour from the code before they can even scope the fix.

This is, in our experience, the difference between an integration that gets steadily more reliable over a couple of years of small fixes, and one that gets rewritten from scratch every time a key person leaves, because nobody left behind could explain with confidence what the system was actually supposed to do.

Insights

Apply this to your store.

An audit turns the general principle into a specific list of changes, ordered by what actually pays back.