How to Monitor Shopify Webhooks
Shopify removes your webhook subscription if it keeps failing. The retry window is much shorter than most guides claim.
Monitoring Shopify webhooks matters more than monitoring most webhook integrations, because Shopify does not just drop failed events. It removes the subscription, and then no events of that topic are sent at all.
Once that happens there is nothing to fail and nothing to alert on. Orders continue, your handler sits idle, and everything looks calm.
The retry numbers most articles get wrong
Shopify's current troubleshooting documentation states that failed webhook calls are retried up to eight times over a four-hour period, and that the subscription is removed if failures persist.
A great deal of writing online still cites 19 retries over 48 hours. That figure is out of date, and if your recovery planning assumes it, you have roughly a twelfth of the time you think you do.
Four hours is short. A failure that begins during a deploy at 18:00 on Friday has exhausted its retries before anyone opens a laptop.
| Constraint | Value | Consequence |
|---|---|---|
| Response timeout | 5 seconds, not configurable | Any inline processing risks a timeout |
| Retries | Up to 8 attempts | Front-loaded, mostly within the first hour |
| Retry window | About 4 hours | Does not survive an overnight outage |
| After exhaustion | Subscription removed | All future events of that topic stop |
| Signature header | X-Shopify-Hmac-SHA256 | Base64 HMAC of the raw body |
Respond in well under five seconds
Five seconds sounds generous until you include TLS negotiation, framework boot, database connection and whatever your handler does. Verify the HMAC, write the raw payload to a queue, return 200, and do everything else afterwards.
Use X-Shopify-Event-Id as your idempotency key. Retries reuse it, so recording processed IDs and discarding repeats prevents double-fulfilling an order.
Monitor the worker, and monitor the gap
Ping from the queue worker after the event is processed, not from the endpoint that returns 200. The endpoint returning 200 is exactly the thing that can be true while nothing works.
Set the interval from real order data. A store averaging 30 orders a day has a longest overnight gap of perhaps eight hours; a store doing 300 a day rarely goes quiet for more than one. Read it from your own order timestamps rather than picking a round number.
The trailing || true matters. A monitoring endpoint having a bad minute should never be the reason a Shopify order fails to process.
Detect a removed subscription directly
Because a removed subscription produces silence rather than errors, the definitive check is to ask Shopify what subscriptions currently exist and compare against what you expect.
Run this daily from a scheduled job. If the count or the topic list differs from your expected set, re-register and alert. This is the only check that catches the removal on the day it happens rather than when a customer complains.
If your app was created in the Dev Dashboard, the Monitoring page also shows delivery counts and response times per topic for the last seven days, which is useful for spotting a topic that is degrading before it is removed.
Related guides
For the general pattern see webhook monitoring. Payment-side events are covered in monitoring Stripe webhooks.