Your Shopify store generates a constant stream of events. Orders get placed. Inventory changes. Customers update their profiles. Fulfillments ship. The question is how your systems learn about these events in real time without hammering the Shopify API with endless polling requests.

That is where webhooks come in. Shopify webhooks let your store push event notifications to your external systems the moment something happens. Instead of asking “has anything changed yet?” every few minutes, your application simply waits to be told.

This guide walks through how Shopify webhooks work, how to set them up correctly, and how to build an event-driven architecture that stays reliable as your store scales.

What Are Shopify Webhooks?

A webhook is an HTTP callback. When a specific event happens in your store, Shopify sends an HTTP POST request to a URL you control. The request body contains a JSON payload describing the event.

Think of it as a reverse API call. Normally your app calls Shopify. With webhooks, Shopify calls your app.

Here is a simple example. A customer places an order. Shopify immediately fires an orders/create webhook to your endpoint. Your server receives the order data and can update your warehouse system, send a confirmation to a CRM, or trigger a fraud check.

This push model is the foundation of event-driven architecture for Shopify apps, where your systems react to events instead of constantly checking for them.

Why Event-Driven Beats Polling

Polling means repeatedly calling the Shopify API to check for new data. It works, but it wastes resources and introduces lag.

Compare the two approaches:

Factor Polling Webhooks
Latency Minutes of delay Near real-time
API usage High, constant calls Low, event triggered
Rate limit risk High Minimal
Scalability Poor at volume Strong
Resource cost Wasteful Efficient

Webhooks win on nearly every metric. They reduce load on both your systems and Shopify. They deliver data faster. And they free your developers from writing complex polling schedules.

Moving to an event-driven Shopify model is one of the highest-leverage architecture decisions you can make for a growing store.

Common Shopify Webhook Topics

Shopify offers dozens of webhook topics. Each topic represents a type of event. You subscribe only to the ones you need.

Here are the most widely used topics:

Topic Fires When
orders/create A new order is placed
orders/updated An order is modified
orders/fulfilled An order ships
products/update A product changes
inventory_levels/update Inventory count changes
customers/create A new customer registers
app/uninstalled Your app is removed
checkouts/create A checkout starts

Subscribe selectively. Each webhook you register adds traffic to your endpoint. Only listen for events your application actually needs to handle.

Shopify Webhook Setup: Three Methods

You can register Shopify webhooks in three ways. The right choice depends on your use case.

1. Admin Dashboard

The Shopify admin lets you create webhooks manually under Settings then Notifications. This works for simple integrations like sending order data to a single endpoint.

It is quick but limited. You cannot easily version or script these webhooks, and they are tied to the store rather than an app.

2. REST Admin API

For programmatic control, use the REST Admin API. This suits custom integrations where you need to create webhooks during an app install flow.

curl -X POST \
  https://your-store.myshopify.com/admin/api/2024-01/webhooks.json \
  -H "X-Shopify-Access-Token: your_access_token" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook": {
      "topic": "orders/create",
      "address": "https://your-app.com/webhooks/orders-create",
      "format": "json"
    }
  }'

3. GraphQL Admin API

Modern Shopify app development favors GraphQL. The webhookSubscriptionCreate mutation registers webhooks and returns a clean response.

mutation {
  webhookSubscriptionCreate(
    topic: ORDERS_CREATE
    webhookSubscription: {
      callbackUrl: "https://your-app.com/webhooks/orders-create"
      format: JSON
    }
  ) {
    webhookSubscription {
      id
    }
    userErrors {
      field
      message
    }
  }
}

If you are new to GraphQL, our Shopify GraphQL API guide covers how to query store data efficiently and build mutations like this one.

Verifying Webhook Authenticity

Here is a critical point. Anyone who knows your webhook URL can send fake requests to it. You must verify that every incoming webhook actually came from Shopify.

Shopify signs each webhook with an HMAC header called X-Shopify-Hmac-Sha256. You verify it by computing an HMAC of the raw request body using your app secret, then comparing it to the header value.

<?php
function verifyWebhook($data, $hmacHeader, $secret) {
    $calculatedHmac = base64_encode(
        hash_hmac('sha256', $data, $secret, true)
    );
    return hash_equals($hmacHeader, $calculatedHmac);
}

$rawBody = file_get_contents('php://input');
$hmac = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'] ?? '';
$secret = getenv('SHOPIFY_APP_SECRET');

if (!verifyWebhook($rawBody, $hmac, $secret)) {
    http_response_code(401);
    exit('Unauthorized');
}

Always use a constant-time comparison like hash_equals to prevent timing attacks. For a deeper look at hardening your endpoints, read our guide on building secure webhook verification systems.

Never trust a webhook until it passes verification. This single step protects your store from spoofed orders, fake inventory updates, and other malicious payloads.

Responding Fast and Processing Later

Shopify expects a response within five seconds. If your endpoint takes longer, Shopify marks the delivery as failed and retries.

This creates a trap. If you try to process the entire webhook inline, slow database writes or third-party API calls can push you past the timeout.

The solution is simple. Acknowledge the webhook immediately, then process the payload asynchronously.

<?php
// After verification passes
http_response_code(200);

// Flush response to Shopify
if (function_exists('fastcgi_finish_request')) {
    fastcgi_finish_request();
}

// Now push the job to a queue for background processing
enqueueWebhookJob($rawBody);

This pattern separates receiving from processing. Your endpoint stays fast and reliable even when the downstream work is slow.

Queue-based processing is the backbone of this approach. Our article on queue-based processing for Shopify webhooks explains how to structure workers, retries, and backpressure correctly.

For high-volume stores, you may want to explore full async event processing architectures that decouple every stage of the pipeline.

Handling Duplicate Events

Shopify guarantees at-least-once delivery. That means you will occasionally receive the same webhook twice.

If your processing is not idempotent, duplicates cause real damage. You might charge a customer twice, create two warehouse orders, or double-count inventory.

The fix is idempotency. Each webhook includes a unique X-Shopify-Webhook-Id header. Store processed IDs and skip any you have already handled.

<?php
$webhookId = $_SERVER['HTTP_X_SHOPIFY_WEBHOOK_ID'] ?? '';

if (alreadyProcessed($webhookId)) {
    http_response_code(200);
    exit;
}

markAsProcessed($webhookId);
// continue processing

Our detailed walkthrough on handling duplicate Shopify events covers edge cases like race conditions between duplicate deliveries and how to design idempotency keys that survive restarts.

The Ordering Problem

Webhooks do not arrive in guaranteed order. An orders/updated event can reach your endpoint before the orders/create event that logically preceded it.

This happens because Shopify delivers webhooks in parallel across its infrastructure. Network timing and retries scramble the sequence.

Design your consumers to tolerate out-of-order events. Use timestamps or version fields in the payload to decide whether an incoming event is newer than what you already stored.

We cover this challenge in depth in our guide to ordering problems in Shopify webhooks, including strategies like event sequencing and state reconciliation.

For stores that process orders at scale, out-of-order events combined with concurrent processing can cause data corruption. Learn how to defend against this in our piece on preventing race conditions in Shopify order processing.

Building Reliable Webhook Consumers

A reliable consumer does more than parse JSON. It verifies, deduplicates, queues, and recovers from failure gracefully.

Here is a checklist for a production-grade consumer:

Requirement Why It Matters
HMAC verification Blocks spoofed requests
Fast 200 response Avoids Shopify retries
Idempotency check Prevents duplicate side effects
Async queue Keeps the endpoint responsive
Structured logging Enables debugging and replay
Error handling Prevents silent data loss

Each of these pieces works together. Skip one and your pipeline develops cracks that only surface during peak traffic.

Our guide on building reliable Shopify webhook consumers walks through a reference implementation that ties all of these pieces together.

Retry Strategies and Dead Letter Queues

Sometimes processing fails. A database is down. A third-party API times out. You need a plan for these failures.

Shopify retries failed webhook deliveries over 48 hours before giving up. But you should not rely solely on Shopify retries. Build your own internal retry logic for jobs that fail after you have already acknowledged the webhook.

When a job fails repeatedly, move it to a dead letter queue. This isolates poison messages so they do not block healthy processing. You can then inspect and replay them manually.

Read our guides on Shopify webhook retry strategies and dead letter queues for Shopify webhooks to design a resilient failure-handling layer.

For cases where you need to reprocess historical events, a Shopify webhook replay system lets you re-run past deliveries without disrupting live traffic.

Scaling Your Webhook Infrastructure

A small store might handle webhooks on a single server. A high-volume store cannot.

During a flash sale, order webhooks can spike from a handful per minute to thousands. Your infrastructure must absorb that burst without dropping events.

Key scaling techniques include:

  • Horizontal scaling of consumer workers
  • Load balancing across multiple endpoints
  • Autoscaling queue consumers based on backlog depth
  • Partitioning events by shop or resource type

Our article on scaling webhook infrastructure breaks down how to architect for these spikes. If flash sales are a recurring concern, also review our guidance on scaling Shopify systems during flash sales.

As your event volume grows, you may graduate from simple queues to a full Shopify event streaming architecture using platforms like Kafka or Kinesis for durable, replayable event logs.

Webhooks in Real Integration Scenarios

Webhooks rarely live in isolation. They feed larger systems that keep your operations in sync.

Consider a few common patterns:

Inventory sync across channels. An inventory_levels/update webhook keeps your warehouse and marketplaces aligned. This is central to any distributed Shopify inventory sync design.

ERP connectivity. Order webhooks push financial and fulfillment data into your ERP. Our Shopify ERP integration architecture guide shows how to structure this flow reliably.

Warehouse management. Fulfillment webhooks drive your WMS. Explore the common pitfalls in our article on Shopify WMS integration challenges.

Order routing. For merchants with multiple fulfillment locations, webhooks trigger enterprise order routing architectures that decide where each order ships from.

Across all of these, you must account for eventual consistency in Shopify integrations, since downstream systems will not always reflect the latest state instantly.

Eventual Consistency and Data Integrity

When you adopt event-driven design, you accept that your systems will be briefly out of sync. Shopify holds the source of truth, and your external systems catch up as events flow in.

This is normal and manageable. The key is designing your reads and writes to tolerate temporary gaps.

Caching plays a role here too. Well-placed caching layers in Shopify ecosystems reduce API load while webhooks keep the cache fresh. When an event fires, you invalidate the relevant cache entry rather than refreshing everything.

Testing and Monitoring Webhooks

You cannot ship webhook code blind. Test it thoroughly before and after deployment.

Use the Shopify CLI to trigger test webhooks locally. Tools like ngrok expose your local endpoint to the internet so Shopify can reach it during development.

In production, monitor these signals:

Metric What to Watch
Delivery success rate Sudden drops signal endpoint issues
Processing latency Rising latency warns of queue backlog
Error rate Spikes reveal broken consumers
Queue depth Growing depth means you are falling behind

Set alerts on these metrics. A silent webhook failure can corrupt data for hours before anyone notices.

If you are building your first integration, our guide on how to build and deploy a Shopify app from scratch covers the end-to-end setup including webhook registration during app install.

Putting It All Together

A mature webhook architecture follows a clear flow. Shopify fires an event. Your endpoint verifies the HMAC. It checks for duplicates. It returns a fast 200. It queues the payload. A worker processes the job with retries and a dead letter fallback. Monitoring watches the whole pipeline.

Build in this order and you get a system that stays correct under load, recovers from failures, and scales with your store.

For enterprises stitching together many systems, these patterns combine into scalable Shopify integration patterns that power high-traffic Shopify architecture without breaking.

Webhooks turn your Shopify store into a reactive, real-time platform. Set them up carefully, verify every request, process asynchronously, and plan for failure. Do that and your event-driven architecture will serve your store well through every spike and every scale milestone.

Frequently Asked Questions

What are Shopify webhooks used for?

Shopify webhooks send real-time event notifications from your store to external systems. They let you react instantly to orders, inventory changes, fulfillments, and other events without polling the API.

How do I verify a Shopify webhook is authentic?

Compute an HMAC SHA256 of the raw request body using your app secret, then compare it to the X-Shopify-Hmac-Sha256 header using a constant-time comparison like hash_equals. Reject any request that fails.

Why does Shopify send duplicate webhooks?

Shopify uses at-least-once delivery, so the same event can arrive more than once. Use the X-Shopify-Webhook-Id header to deduplicate and make your processing idempotent.

How fast must my webhook endpoint respond?

Shopify expects a response within five seconds. Return a 200 immediately after verification, then process the payload asynchronously through a queue to avoid timeouts.

What happens when a webhook delivery fails?

Shopify retries failed deliveries for up to 48 hours. You should also build internal retry logic and a dead letter queue to handle jobs that fail after you acknowledge the webhook.

Can webhooks arrive out of order?

Yes. Shopify delivers webhooks in parallel, so events can arrive out of sequence. Use timestamps or version fields in the payload to handle ordering correctly.

Should I use REST or GraphQL to register webhooks?

Both work, but GraphQL is the modern choice for Shopify app development. The webhookSubscriptionCreate mutation gives cleaner responses and aligns with current API direction.

Your Trusted Shopify Partner.

Get in touch with our expert Shopify consultants today and let’s discuss your ideas and business requirements.