Why this failure happens
A store may appear to create two shipments, deduct inventory twice, or send duplicate notifications even though the merchant placed one order. A common cause is treating webhook delivery as exactly-once execution. Shopify documents that deliveries can repeat after timeouts or retries. The practical implication is that a successful HTTP request and a unique business action are not interchangeable. A webhook receiver must authenticate each delivery, acknowledge it promptly, and make downstream effects safe to repeat. This guide applies to custom Shopify apps and integrations, not to a particular newly announced platform incident.
Prerequisites and a safe baseline
Identify the HTTPS webhook endpoint, app client secret stored in a secret manager, persistent database, queue worker, and business side effects such as inventory, fulfillment, or email. Create a staging store or isolated test subscription. Capture request headers, topic, shop domain, delivery identifier, response status, and processing duration, but do not log customer addresses or complete payloads unnecessarily. Before modifying production, determine whether the current handler parses JSON before verifying its signature; that can change the bytes used for the digest. Back up the webhook processing table and document the rollback plan.
Step 1: authenticate the raw delivery
For HTTPS deliveries, Shopify supplies X-Shopify-Hmac-SHA256, a base64 HMAC computed using the app secret and the raw request body. Read the raw bytes before a JSON parser transforms them. Compute HMAC-SHA256 with the correct secret, decode the received signature, and compare equal-length byte arrays with a constant-time comparison. Reject missing or mismatched signatures without performing side effects. Framework middleware may already handle verification; avoid double-verifying against a reserialized JSON object. For event delivery transports other than HTTPS, follow Shopify's transport-specific authentication documentation rather than assuming the same header applies.

Step 2: reserve an idempotency key transactionally
Create a durable table with shop identifier, subscription or topic where appropriate, delivery ID, status, first_seen_at, processed_at, and a unique constraint on the intended deduplication scope. For HTTPS webhooks, Shopify documents X-Shopify-Webhook-Id as a delivery identifier and X-Shopify-Event-Id as a correlation identifier for the underlying merchant action. They are not interchangeable. Insert the delivery record atomically; if the unique constraint reports a prior delivery, return success without repeating work. Do not use a check-then-insert sequence without a unique index: two simultaneous requests can both pass the check.
Step 3: separate receipt from business processing
After authentication and durable enqueue, acknowledge quickly with a successful HTTP response. Have a worker claim queued records using a transaction or lease. Use stable business keys for irreversible effects: for example, a fulfillment operation can have its own unique operation key derived from shop, order and intended action. A delivery ID alone cannot prevent two distinct webhook subscriptions from triggering the same business side effect. Commit inventory adjustments and their ledger entry in one transaction where possible. For third-party APIs, send their supported idempotency key and reconcile ambiguous timeouts instead of blindly retrying.
Step 4: test failures, retries and reconciliation
Replay the same signed test delivery twice and verify that exactly one effect occurs. Simulate two concurrent workers, a crash after database commit but before acknowledgement, and a downstream API timeout. Verify that the delivery record transitions from received to processing to completed or retryable failure; an early 'processed' flag before the actual effect can permanently drop work. Use a dead-letter queue for repeatedly failing events, with alerting and a controlled replay path. Compare Shopify orders and your local order ledger over a bounded period to identify missing events without creating duplicate shipments.
Troubleshooting and operational guardrails
A spike in HMAC failures usually points to the wrong app secret, transformed request bytes, or a misconfigured proxy; it is not evidence that Shopify sent invalid data. Duplicate effects despite a delivery-ID constraint suggest a second subscription, another ingestion path, or non-idempotent downstream code. Missing updates despite successful responses suggest enqueue failures or a worker stuck in processing. Record counts for received, authenticated, duplicate, queued, completed, retried and dead-lettered deliveries. Avoid exposing raw webhook bodies or secrets in logs. For stores with multiple fulfillment partners, assign ownership of each side effect explicitly.
What to change in an existing integration
Audit every handler by topic and list the business effects it can trigger. Add signature verification first, then durable deduplication, then operation-level idempotency and reconciliation. Deploy behind a feature flag and monitor a representative traffic window before removing the legacy path. Brightery's engineering teams can use this same event-processing pattern when connecting ecommerce platforms, payment services and inventory systems; the critical outcome is a provable single business effect, not merely a green webhook delivery dashboard.
Primary documentation and further reading
Shopify: Verify webhook deliveries; Shopify: Verify Events deliveries. Consult the official documentation before deploying changes to production.
0 Responses
Share your perspective and continue the conversation.
No responses yet
Be the first to share your thoughts.
Join the conversation