GET A FREE STORE AUDITFREE AUDIT

SEP 17, 2026 · UPDATED OCT 8, 2026 · 8 MIN READ

Webhooks, retries and the orders you never processed

Webhooks are how most Shopify integrations hear about orders. They can also arrive more than once, out of order, and sometimes not at all.

A hand steadying a wrapped parcel on a small conveyor belt running from a model shop with a sign reading SHOP to shelves of boxes

A Shopify webhook is an HTTP POST that Shopify sends to your endpoint when something happens: an order is created, a product changes, a customer is updated. Shopify retries a failed delivery 8 times over the next 4 hours, and after 8 consecutive failures it deletes the subscription if it was created through the Admin API, so an integration that returns errors can stop receiving events entirely. Shopify minimizes duplicates but does not rule them out, and it does not guarantee ordering, so an endpoint that assumes exactly-once, in-order delivery will double-process some records and mis-sequence others.

IN SHORT

  • The same webhook can arrive more than once. Your endpoint must be safe to call twice with the same payload.
  • Delivery order is not guaranteed. An update can arrive before the create it depends on.
  • After 8 consecutive failures, a subscription created through the Admin API is deleted. The only notice is an email to the app’s emergency developer address.
  • Return 200 fast and do the work asynchronously. Shopify allows one second to connect and five seconds for the whole request.
  • Reconcile against the API on a schedule. Webhooks are a notification system, not a source of truth.

What Shopify actually guarantees

It guarantees that it will try. It does not guarantee that the attempt succeeds, that it happens once, or that events arrive in the order they occurred.

That is not a Shopify shortcoming. It is how webhook delivery works everywhere, and the alternatives are worse. Yet integrations are routinely built as though delivery is reliable and ordered, and they work in testing because testing sends one event at a time to a healthy endpoint.

They fail during peak, when volume is high and your endpoint is slow, which is the worst possible time to discover the assumption.

What happens when the same webhook arrives twice?

Anything that is not idempotent runs twice. Shopify minimizes duplicate deliveries but says your app might still receive the same webhook more than once. If your handler creates a record in the ERP on receipt, you now have two. If it decrements stock, you have decremented twice.

The fix is idempotency, and it is not complicated. Record the X-Shopify-Webhook-Id header, which Shopify says to use to deduplicate individual deliveries, and on a repeat return 200 and do nothing. X-Shopify-Event-Id is a different thing: it is shared across deliveries from the same merchant action, so it correlates deliveries rather than deduplicating them.

The part teams get wrong is where that record lives. If the deduplication table is in the same transaction as the work, it is reliable. If it is in memory, it survives exactly as long as the process does, which during a deploy is not long.

Order is not guaranteed, and it matters more than it sounds

A product update can arrive before the product create. An order fulfillment can arrive before the order. Shopify’s best practices state that it does not guarantee ordering within a topic, or across topics for the same resource.

Two defenses. First, make handlers tolerant: an update for a record you have never seen should fetch the record from the API rather than erroring or creating a half-populated row. Second, use timestamps rather than arrival order when deciding whether an update is newer than what you hold. Shopify recommends the X-Shopify-Triggered-At header; the payload’s updated_at is the alternative.

Return 200 quickly, then do the work

Shopify allows a one-second connection timeout and a five-second timeout for the entire request. If your handler calls an ERP, transforms data and writes to a database before responding, it will time out under load, and a timeout is a failure, which starts the retry clock.

The pattern that survives is: verify the HMAC (the X-Shopify-Hmac-SHA256 header), write the raw payload to a queue, return 200. Everything else happens in a worker that can be slow, can retry on its own terms, and can fail without Shopify knowing or caring.

This also makes replay possible. When a downstream system has been broken for six hours, you want the last six hours of payloads sitting in a queue rather than gone.

  • Verify the HMAC before trusting anything in the payload. An unverified endpoint is an open write path into your systems.
  • Persist the raw body before parsing it, so a parsing bug is recoverable.
  • Return 200 for anything you have accepted, including duplicates you are ignoring.
  • Return a non-2xx only when you want a retry; Shopify counts any response outside the 200 range, redirects included, as a failure. Failing on a bad payload buys you eight pointless attempts and, if it persists, a deleted subscription.
  • Log the webhook id and topic on every request, or debugging at 2am is guesswork.

What happens if your endpoint keeps failing?

Shopify stops delivering. After 8 consecutive failures it automatically deletes the subscription if it was configured using the Admin API, and removed subscriptions receive nothing until you recreate them. The only warning is an email to the app’s emergency developer address, which is easy to miss. Orders simply stop arriving.

The usual discovery route is someone in operations noticing that the ERP has fewer orders than Shopify does, often days later, often during a busy week.

Two things prevent it. Monitor the count of events received per topic per hour and alert on zero, because zero is a number that never occurs naturally on a trading store. And reconcile: on a schedule, query the API for records changed since your last sync and compare against what you hold. Webhooks tell you quickly; the API tells you truthfully. Shopify itself recommends reconciliation jobs, and many GraphQL queries accept updated_at filters for exactly this. The same cost and pagination rules apply to that job, which is what the Admin GraphQL API post covers.

The only warning is an email to the app’s emergency developer address, which is easy to miss.
Aman Jain & Krunal Prajapati

What to check on an integration you inherited

If you have an integration you did not build, these five questions establish how much trouble you are in, quickly.

  • Is the HMAC verified on every endpoint, or only on some?
  • What happens if the same payload arrives twice? Is there a deduplication key, and where does it live?
  • Does the endpoint return 200 before doing the work, or after?
  • Is there a reconciliation job, and when did it last find a discrepancy?
  • Is anyone alerted when events stop arriving?

Questions this raises

How long does Shopify retry a failed webhook?

Shopify retries 8 times over the next 4 hours. After 8 consecutive failures a subscription configured through the Admin API is deleted, and no further events arrive until it is recreated, which is why monitoring for the absence of events matters more than monitoring for errors.

Are Shopify webhooks delivered in order?

No. Shopify does not guarantee ordering within a topic or across topics for the same resource, so an update can arrive before the create it relates to. Use timestamps, such as the X-Shopify-Triggered-At header, rather than arrival order to decide whether the data you are holding is stale.

Should an integration use webhooks or polling?

Both. Webhooks for latency, so the common case is fast, and a scheduled reconciliation against the API for correctness, so missed or mis-ordered events are caught. Webhooks alone will drift; polling alone is slow and expensive.

Why verify the HMAC on a webhook endpoint?

Because without it anyone who learns the URL can post arbitrary data to a system that writes into your ERP, your fulfillment or your accounting. The header is a signature of the raw body using your app secret. Verify it before parsing, and reject anything that does not match.

General information, not legal, tax or financial advice. Rates, limits and deadlines come from the vendors and authorities named, and they change: check the linked source before relying on one.

PART OF OUR SERVICE

Wire Shopify into the systems your business already runs on

ERP, subscriptions, custom apps and configurators

EXPLORE INTEGRATE →

NEXT STEP

Free store audit

A senior Shopify engineer reviews your storefront, theme performance and checkout, then sends a prioritized list of fixes.

A hand gestures towards a small shop doorway tied with colorful ribbons, with a tablet on a workbench inside