Back to Blog
ShopifyGraphQLWebhooksAPI

Named Webhook Subscriptions: Shopify's Best 2026-04 Quality-of-Life Update

Shopify's 2026-04 API introduces optional names for webhook subscriptions. It's a small change that solves a genuinely annoying routing problem that every multi-webhook app has faced.

5 min read
Named Webhook Subscriptions: Shopify's Best 2026-04 Quality-of-Life Update

Among all the changes in Shopify's 2026-04 API release, this one deserves more attention than it's getting. Named webhook subscriptions aren't glamorous, but they fix a concrete problem that anyone who has built multi-integration Shopify apps will recognize immediately.

The Problem: Routing Webhooks Without Parsing Payloads

Imagine you're building a Shopify app that subscribes to orders/paid with two different purposes: one to trigger a fulfillment workflow, and another to sync order data to an external analytics platform. Both subscriptions are on the same topic, both hit the same endpoint.

Until 2026-04, the only way to route these internally was to parse the webhook payload body and inspect the data to determine which handler to invoke. On high-order-volume stores, that means parsing potentially large JSON bodies just to route events — before you can even decide whether you care about a particular webhook.

Parsing the full webhook payload just to route it creates unnecessary CPU overhead and adds latency to acknowledgment. Shopify requires a 5-second response window — time you can't spare on expensive JSON parsing before routing.

The Solution: Names in Request Headers

With named webhook subscriptions, you assign a name when creating the subscription. Shopify then includes this name in the request headers when delivering the webhook. Your endpoint can read the header and route the event instantly — without touching the body — and then pass it to the appropriate handler.

graphql
mutation CreateWebhookSubscription {
  webhookSubscriptionCreate(
    topic: ORDERS_PAID
    webhookSubscription: {
      format: JSON
      callbackUrl: "https://your-app.dev/webhooks/orders"
      name: "fulfillment_trigger"
    }
  ) {
    webhookSubscription {
      id
      topic
      name  # new in 2026-04
    }
    userErrors {
      field
      message
    }
  }
}

The header Shopify sends on delivery is X-Shopify-Webhook-Name (the exact header name should be verified in the official docs). Reading a request header is microseconds; parsing a 10KB JSON body is milliseconds. At scale, this matters.

How to Use Named Subscriptions in TOML

If you declare webhook subscriptions in your shopify.app.toml (the declarative approach), the name field is now available there too:

toml
[[webhooks.subscriptions]]
topics = ["orders/paid"]
uri = "/webhooks/orders"
name = "fulfillment_trigger"

[[webhooks.subscriptions]]
topics = ["orders/paid"]
uri = "/webhooks/orders"
name = "analytics_sync"

Naming Rules and Uniqueness Constraints

The 2026-04 spec defines the following constraints on subscription names:

  • Maximum 50 characters
  • Allowed characters: alphanumeric, underscores (_), hyphens (-)
  • Admin API subscriptions: names must be unique per shop
  • Declarative (TOML) subscriptions: names must be unique per app
  • The name field is optional — existing webhooks without names continue to work without changes

Practical Router Pattern

Here's a practical webhook handler pattern that takes full advantage of named subscriptions:

typescript
// webhooks/orders.ts
const WEBHOOK_HANDLERS: Record<string, (payload: unknown) => Promise<void>> = {
  fulfillment_trigger: handleFulfillmentTrigger,
  analytics_sync: handleAnalyticsSync,
  inventory_update: handleInventoryUpdate,
};

export async function POST({ request }: ActionFunctionArgs) {
  const webhookName = request.headers.get('x-shopify-webhook-name');
  const handler = webhookName ? WEBHOOK_HANDLERS[webhookName] : null;

  if (!handler) {
    // Fall back to topic-based routing if no name
    // ...
  }

  // Process body only once, only when needed
  const payload = await request.json();
  await handler(payload);
  return new Response(null, { status: 200 });
}

Named webhooks work best in combination with multiple subscriptions per topic filtered by different criteria. You get both routing clarity AND conditional delivery — a powerful combination for complex app architectures.

It's a small feature. It took probably a week of engineering work at Shopify. But it's the kind of quality-of-life improvement that makes building apps significantly less painful in practice, and the 2026-04 release has several more of these.

Written by

Sultan Ahmad

Shopify Engineering, Artiple Web

← More articles