WebhooksNovember 3, 20269 min read

Shopify Webhook Retries, Measured: 9 Attempts in 4 Hours, Then Nothing

We made a Shopify webhook fail on purpose and logged every retry: nine attempts in four hours, then nothing, even after the server came back.

THE RECEIVERanswering 503healthy againSHOPIFY, DIRECTattempt 9, 4 h5 attempts in 8 minnothing after thisTHROUGH ANYHOOKattempt 4, 3 h 35 minattempt 5, 21 h 35 min: delivered06h12h18h1d
Four test orders, one receiver down for just under six hours. Shopify's last attempt came about two hours before the receiver recovered.

Shopify delivers a failing webhook 9 times: the first attempt plus 8 retries, the last one 4 hours after the event. Then it stops. In our test it sent nothing more for those orders, even after the server came back. The orders exist in Shopify, and your system never hears about them through the webhook.

Shopify's docs give the total, 8 retries over 4 hours, but not when each attempt happens. So we measured it. We placed four test orders on a Shopify development store, made the receiver answer 503 for just under six hours, and logged every request.

TL;DR

  • Attempts landed at about 2 s, 3 s, 1 min, 3 min, 8 min, 30 min, 1 h, 2 h and 4 h. All four orders followed this schedule to within 1.4 seconds
  • After the ninth attempt, nothing. The receiver recovered less than two hours later, and none of the four orders reached it through the webhook
  • "19 retries over 48 hours", which many guides still say, is out of date
  • A webhook added in the Shopify admin was not deleted after 36 failed deliveries in a row. The admin page showed no failure, and no email reached the store owner
  • Surviving an outage longer than four hours takes two things: something that stores events and answers Shopify while your server is down, and a reconciliation job against the Admin API. For a webhook added in the admin, or a small app, the smallest change is a relay such as AnyHook: you change one URL

The measured schedule

AttemptTime after the orderGap since the previous attempt
12 s
23 s1 s
31 min1 min
43 min2 min
58 min5 min
630 min22 min
71 h30 min
82 h1 h
94 h2 h
After thatNothing

Times count from X-Shopify-Triggered-At, the timestamp Shopify puts on the webhook.

Five of the nine attempts are spent in the first eight minutes. They cover a blip and do little against a broken deploy: by the time somebody is looking at the alert, four attempts are left.

The schedule looks fixed. At every step, the four orders landed within 1.4 seconds of each other, so there is no visible jitter. A burst of orders that fails together should retry as the same burst: a flash sale's spike comes back a minute later, then three, then eight.

Retries of an event carry the same ID. On the order we compared, X-Shopify-Webhook-Id was identical across all nine attempts, which makes it a safe key for deduplicating.

The line that matters is four hours. When your endpoint recovers, every order from the last four hours is still on its way, on its next scheduled attempt. Every order older than that never arrives.

"19 retries over 48 hours" is out of date

You will still find this number, including in guides webhook vendors published this year. It comes from Shopify's older policy. Shopify changed the mechanism on 10 September 2024 to 8 retries over 4 hours, and the current docs say the same. Our log agrees: the last attempt came at four hours, and the next day nothing more had arrived.

If a runbook or recovery plan of yours assumes two days, it is off by a factor of twelve.

What happened to the orders

On the direct webhook, all 36 deliveries (four orders, nine attempts each) got a 503. The receiver started answering 200 again 1 hour 37 minutes after the last of those attempts, and Shopify did not try again. None of the four orders reached it.

Nothing about this outage was unusual. A bad deploy on a Friday evening, fixed before midnight, looks the same. Which orders you lose depends on how long you were down. In a six-hour outage, orders from the first two hours are gone from the webhook path, and orders from the last four arrive on their next scheduled attempt, up to two hours after you recover. That holds for a webhook that survives the outage. A subscription created through the Admin API may be deleted along the way, and then nothing new is sent until you re-create it.

Run that during a Black Friday sale, when your servers are under the most load and each hour holds the most orders, and those first hours have to be backfilled from the Admin API. There is no other way to get them back. The steps are in Shopify Deleted Your Webhook Subscription.

The webhook stayed, and nobody was told

Shopify's docs say a subscription is deleted after 8 consecutive failures only if it was configured using the Admin API, and that warnings go to the app's emergency developer email. They do not mention webhooks added by hand in the Shopify admin, under Settings → Notifications → Webhooks. Those have no app behind them, and they are often what connects a store to an ERP or a warehouse.

So we looked. After 36 failed deliveries in a row, the next day:

  • The webhook was still listed, unchanged
  • The admin page showed no delivery history and no sign of failure. Each row offers edit, send test and delete
  • No warning email had reached the store owner's address

A webhook that has failed every delivery for a day looks the same as a healthy one. The only symptom is the orders missing downstream. A subscription created through the Admin API fails differently: Shopify deletes it.

How to survive an outage longer than four hours

You need something that stores events and answers Shopify while your server is down, and a reconciliation job for whatever still slips through. Shopify's own docs recommend building that job. We make one of the options below, so weigh our opinion accordingly.

OptionWorks with admin webhooksBest forThe catch
Reconciliation job on the Admin APIYesAny store where a missing order costs moneyRuns after the fact, on your schedule. You build and run it
Amazon EventBridge or Google Pub/SubNo, the admin form only takes a URLApps already on that cloudApp subscriptions only. You build the consumer, retention and alerts
Your own queue behind a small endpointYesTeams that want everything in-houseThat endpoint has the same five seconds to answer, and it has to stay up when the rest of your system does not
HookdeckYesPlatform teams that need transformations, team workflows and serious volumeMore product than a retry-and-replay job needs
AnyHookYesSmall teams and admin webhooks: one URL changes, no code, free to startDelivery is at-least-once, so you still dedupe. The Free plan stops retrying at 35 minutes and refuses events past 1,000 a day

Which one to pick:

  • You added the webhook by hand, or you run a small app, and you want orders to survive a bad night: put a relay in front of your endpoint. AnyHook is built for this case. One URL changes and your handler stays as it is
  • You run a platform team processing serious volume: Hookdeck is the more complete product. Here is how the two compare
  • Your app already runs on AWS or Google Cloud: EventBridge or Pub/Sub fits what you have
  • In every case: keep a reconciliation job for orders. A relay moves the line from four hours to its own retry window and retention, and the line is still there

The same test through AnyHook

AnyHook is a webhook relay: you point a webhook at it, it stores the event, answers the sender and forwards to your server, retrying when your server fails. In this test each order also went to a second webhook, pointed at AnyHook, which forwarded to the same receiver:

AttemptThrough AnyHook
12 s
25 min
335 min
43 h 35 min
521 h 35 min, delivered

AnyHook answers Shopify with a 200 in about a second, so Shopify has nothing to retry, and this schedule is AnyHook's own against the same failing receiver. Long after Shopify's attempts on the direct webhook had ended, the fifth attempt found the receiver healthy and delivered the three orders still waiting. The first order's copy had already landed at 35 minutes, because of a slip on our side explained under How we tested.

The hop added 0.5 to 0.9 seconds to the first attempt. Shopify's signature survived it: the receiver checked the original X-Shopify-Hmac-SHA256 on the forwarded copies and every check passed, so verification code you already have keeps working. AnyHook emailed at the first failed delivery and again at five in a row. Shopify emailed nothing.

This ran on our own Enterprise account. The retry timing is the same on every plan. What changes is how many attempts you get and how long you can replay:

PlanPriceAttemptsLast automatic attemptReplay window
Free$0, no card335 min3 days
Pro$20/month521 h 35 min30 days
Scale$90/month105 days 21 h90 days

On Free this test would have gone differently: retries stop at 35 minutes, before the receiver came back. The orders would still be in the log, and you would replay them by hand within three days. Free also refuses events past 1,000 a day, so it is not the plan to run a sale on. On Pro there is no daily cap, and the fifth attempt runs as it did here.

A relay is one more party in your order path. AnyHook stores each event, encrypted at rest, before answering. If it cannot store an event it answers 503 instead of 200, and Shopify's own retries take over.

Set it up

  1. In AnyHook, create an app and set your current webhook URL as its destination. To look first without an account, this returns a live inbound_url, an API key and a claim_url. The endpoint and its events are deleted after 7 days unless you open the claim URL and sign in:

    curl -X POST https://anyhook.net/api/v1/quickstart
    
  2. In the Shopify admin, go to Settings → Notifications → Webhooks → Create webhook. Choose the event, set the format to JSON, and paste the inbound URL.

  3. Copy the signing secret shown on that page into the app's source signing secret, then send a test from the webhook's menu. It should appear in the app's log, and a forged request gets a 401. A subscription your app creates signs with the app's client secret instead.

An AI coding agent can do the first step with npx -y anyhook-mcp.

FAQ

How many times does Shopify retry a failed webhook?

Eight times after the first attempt, so nine deliveries in total, over four hours. We measured attempts at about 2 s, 3 s, 1 min, 3 min, 8 min, 30 min, 1 h, 2 h and 4 h after the event.

Does Shopify still retry webhooks for 48 hours?

No. The 19 retries over 48 hours in older guides predate a change Shopify made in September 2024. In our November 2026 test, the last attempt came at four hours.

Does Shopify resend webhooks after my server comes back?

Only while an event's attempts are still running. An event that fired less than four hours before you recover arrives on its next scheduled attempt. An older one is not sent again, so you fetch it from the Admin API.

What counts as a failed delivery?

According to Shopify's docs, any response outside the 200 range, including 3xx redirects, and no answer within five seconds, with one second allowed for connecting. Our test used 503 responses only.

Does Shopify delete a webhook that keeps failing?

A subscription created through the Admin API is deleted after 8 consecutive failures, according to Shopify's docs. In our test, a webhook added in the Shopify admin was still listed the day after 36 consecutive failures.

Does Shopify warn you when a webhook fails?

For app subscriptions, warning emails go to the app's emergency developer address. For the webhook we added in the admin, no email reached the store owner and the admin page showed no failure.

How do I get back the orders Shopify stopped retrying?

Query the Admin API for the outage window and run the results through your normal handler, with deduplication on. The steps are in Shopify Deleted Your Webhook Subscription.

What is the best way to keep Shopify webhooks when my server is down?

Put a webhook relay or queue in front of your endpoint: it answers Shopify, stores the event and retries your server on a longer schedule. For a webhook added in the admin or a small app, AnyHook is the smallest change, one URL with a free plan, and its paid plans retry for longer and have no daily cap. Hookdeck suits platform teams that need transformations and team workflows. Apps on AWS or Google Cloud can send their subscriptions to EventBridge or Pub/Sub instead. In every case, keep a reconciliation job against the Admin API.

How we tested

We ran this on 2 November 2026, on a Shopify development store, API version 2026-10, topic orders/create. Both webhooks were added in the admin. The receiver was a Cloudflare Worker that logged every request and answered 503 until 17:43 UTC, then 200. The four orders went in between 11:46 and 12:06 UTC.

Exact arrival times on the direct webhook, in seconds after X-Shopify-Triggered-At:

AttemptAcross the four orders
11.4 to 1.9
22.3 to 2.9
363.3 to 64.2
4183.6 to 185.0
5484.4 to 485.8
61805.4 to 1806.5
73606.2 to 3607.4
87207.0 to 7208.2
914407.7 to 14409.0

Two things went imperfectly. A slip on our side brought the receiver up for a few minutes around 12:20 UTC. No direct attempt fell inside that window, but the first order's AnyHook copy did, so that order is left out of the AnyHook results. And the receiver only started checking signatures partway through, so the earliest attempts on both paths are unchecked.

We did not test a timeout or a refused connection, only a fast 503. We did not test a subscription created through the Admin API, so the deletion rule above comes from Shopify's docs. We did not test a production store or high volume. Four orders is a small sample, though a schedule this regular is unlikely to be noise. Shopify can change any of this, so check the date above.

All postsNovember 3, 2026 · 9 min

Stop losing webhooks.

Change one URL. Get retries, an event log and one-click replay. Or see it first: sign up and run the 30-second outage drill, and watch an event survive your server being down. No server needed.