Upcoming changes to Events

We really appreciate the community for building with Events in Developer Preview, and your feedback is actively helping us improve the contract before Events go to stable in 2026-10.

Across Partner conversations, DotDev workshops, and existing subscriptions, we heard four places where the current behavior is harder to understand or build against than it should be:

  • fields_changed tells you which path changed, but it cannot distinguish between a path being added, updated, or removed.
  • Deleting a resource can produce follow-up update events for children that no longer exist.
  • A parent trigger path such as product.variants behaves like a wildcard, but the syntax does not make that breadth clear.
  • Redundant shopify-event-id and shopify-resource-id headers, which we’re removing before the stable release.

We’re making updates to address this feedback before we lock the Events contract. All breaking changes will roll out on September 16, 2026, and if you’re using Event in your apps, you’ll need to update your subscription configuration and payload handling. These changes apply to Events subscriptions and Classic Webhook subscriptions stay unaffected.

Additionally, we’re also introducing the ability to have a per subscription api_version override, so you can migrate API versions incrementally.

1. fields_changed will describe how each path changed

Today, adding and removing a variant produces the same fields_changed in the payload:

"fields_changed": [
  "product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456']"
]

You know which path changed, but you cannot tell whether it appeared or disappeared without making a query and inferring what happened from the result. Starting September 16, 2026, fields_changed becomes an object with three path buckets:

"fields_changed": {
  "added": [],
  "updated": [],
  "removed": []
}

The buckets describe what happened to a path in the developer-visible GraphQL graph:

  • added: A resource or relationship was added, such as adding a variant to a Product.
  • updated: A value changed on an existing resource, such as changing a variant’s price.
  • removed: A resource or relationship was removed, such as removing a variant from a Product.

Adding a variant to a Product remains "action": "update" for the Product, with the variant path in fields_changed.added:

{
  "topic": "Product",
  "action": "update",
  "fields_changed": {
    "added": [
      "product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456']"
    ],
    "updated": [],
    "removed": []
  }
}

Changing the price of an existing variant keeps the path present, so it appears in updated:

"fields_changed": {
  "added": [],
  "updated": [
    "product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456'].price"
  ],
  "removed": []
}

Removing that variant places the same addressable path in removed:

"fields_changed": {
  "added": [],
  "updated": [],
  "removed": [
    "product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456']"
  ]
}

2. Deletes will no longer produce follow-up updates

Deleting a Product with eight variants can produce one Product delete event followed by eight Product update events, one for each cascading variant deletion. Those updates can arrive after the delete and the query for the Product or variant then returns null, because the resource no longer exists.

We’re actively rolling it across all topics, which means deleting a topic resource will produce one delete event. For example, deleting a Product with two variants changes from:

Product delete
Product update for cascading deletion of Variant 456
Product update for cascading deletion of Variant 789

to:

Product delete

The same rule applies when deleting a Metaobject with fields or a Collection with product relationships. Removing one variant from a Product that still exists remains a meaningful Product update:

{
  "topic": "Product",
  "action": "update",
  "fields_changed": {
    "added": [],
    "updated": [],
    "removed": [
      "product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456']"
    ]
  }
}

Independent effects across topics remain the same, which means deleting a Product will still produce a Collection update when that Collection’s membership changes.

create behavior continues producing follow-up update Events, so when a Product and its variants are created, those children exist and can be queried ensuring that every child is observable, including children beyond the first page of a GraphQL connection.

3. Parent trigger paths will use an explicit wildcard

Today, a parent trigger path such as triggers = ["product.variants"] means “subscribe to every triggerable field below product.variants.” The same path can reasonably look like it means only the variants relationship changed, making the wildcard behavior too easy to miss. Starting September 16, 2026, parent paths that subscribe to all supported descendants use a terminal .*:

triggers = ["product.variants.*"]

This makes the existing breadth of the subscription explicit. It does not change which underlying field changes match or affects event volume for an equivalent subscription.

Leaf triggers remain unchanged:

triggers = ["product.variants.price"]
  • product.variants.* means any triggerable field below variants.
  • product.variants.price means only variant price changes.
  • product.options.optionValues.swatch.* means any triggerable field below swatch, including color or image.
  • Omitting triggers continues to mean that any supported change for the topic can qualify the subscription.

Your existing subscriptions will continue to work and the next time you deploy your shopify.app.toml, you’ll have to migrate to the new syntax, if you’re using triggers that require an explicit wildcard.

4. Redundant shopify-event-id and shopify-resource-id are being removed

Events deliveries currently include the shopify-event-id and shopify-resource-id headers. Both headers will be removed on September 16, 2026.

Updated Shopify API packages are available today which handles this change for you, so no additional header migration is required. If your own application code reads either header directly, remove that dependency before September 16, 2026.

What you need to update:

  1. Change code that expects fields_changed to be an array. Read from fields_changed.added, fields_changed.updated, and fields_changed.removed.
  2. Add a terminal .* to every parent trigger path that is intended to match all descendants, your existing subscriptions will continue to work as expected on deploys after September 16, 2026.
  3. Review action: delete handling. A topic resource deletion is now represented by its single delete event, without child-derived updates from the same cascade. Keep handling independent child removals as updates to a surviving immediate parent.
  4. Update your Shopify API packages to their latest versions. This handles the removal of shopify-event-id and shopify-resource-id for you. If you use custom packages, ensure the headers are not required for validation.
  5. Set your Events API version to 2026-10 on October 1, 2026.

These changes will result in a more predictable delete sequence, a payload that tells you how each path changed, trigger syntax that says exactly how broad the subscription is, and a simpler set of delivery headers.

If you’re testing Events today, we’d love to hear how these changes affect your integration. Share your questions or migration feedback below.

Learn more

Read more about Events: https://shopify.dev/docs/apps/build/events-webhooks
Events API reference: https://shopify.dev/docs/api/events/latest

Amazing work @Harshdeep-Shopify we really appreciate your continuous updates on this project. Looking forward to trying it :slight_smile:

Thanks for the great work on this! Easily one of the most high impact releases I’ve seen from Shopify on the dev side. :slight_smile:

Great updates, thanks! Next-gen events are a game changer for us, so happy to have them!

Nice update, good iteration on the design :flexed_biceps:

@Harshdeep-Shopify Couple of questions:

  1. Are webhooks in their current form going to remain part of the Graph API (not deprecated) for the foreseeable future? Any plans for deprecation?
  2. Any plans to include “fields changed” type of features in webhooks OR add ability to subscribe specific stores to specific events only? The issue we have with Events is that it is static configuration set in the app toml file. Our app relies on the ability to have different webhook subscriptions set up for different stores. Ability to subscribe specific stores to specific events would be very useful…
  1. No plans on deprecations yet.
  2. We will not be bringing any features from Events into Classic Webhooks. The ability to subscribe to Events from GraphQL is coming later this year and is actively being worked on - we understand this is a really important feature^

@Harshdeep-Shopify Hello, it seems the changes went live ( Updates to Events payloads and subscription configuration - Shopify developer changelog ).

However, regarding “Redundant shopify-event-id and shopify-resource-id are being removed”.

“Updated Shopify API packages are available today which handles this change for you, so no additional header migration is required. If your own application code reads either header directly, remove that dependency before September 16, 2026.”

It appears the change aren’t available, are they? Aren’t they stuck on: Packages for release by shopify-github-actions-access[bot] · Pull Request #3375 · Shopify/shopify-app-js · GitHub

Current version of https://www.npmjs.com/package/@shopify/shopify-api is still 14.0.1 while the changes seem to be on 15.0.0.

Sorry if the above is incorrect, but would it be possible to check that the Shopify API packages are updated?

Right now, event deliveries are returning 400 errors.

Thank you,
Vincent

Hey @Vincent_Broucke!

Thank you for catching this! Sorry for the failed deliveries this has caused.

We’re temporarily restoring the shopify-event-id and shopify-resource-id headers while we work through the releases^

@Harshdeep-Shopify No problem at all, and thank you for your prompt action!