Next Generation Events Events that arrive "only when the fields you care about change, in the shape you want"
Field-level triggers / payloads defined with your own GraphQL query / fields_changed to show what changed. A next-generation system that solves both the webhook "noise problem" and the "extra API call problem" at once.
1Understand in 30 seconds: How is it different from webhooks?
Traditional webhooks send every "product/update happened" event, and the receiver had to calculate the diff and fetch the fields they needed via a separate API on their own.
Next Generation Events lets you declare "the fields you want," "the shape you want," and "a current-state filter" at subscription time. What you receive is narrowed down in advance, and what changed is made explicit.
Traditional: everything + diff it yourself
You can't tell whether product/update fired on title, tag, or price. It's sent with a fixed schema, and you re-fetch the fields you want separately via GraphQL.
Events: narrowed in advance, precisely targeted
Declare fields with triggers. Define the payload with query. Narrow by current state with query_filter. Show what changed with fields_changed.
2How it works: The 4 steps to event delivery
② and ③'s "pre-filtering" is the key. Noise is dropped before it reaches your endpoint, so your app no longer "burns CPU just to decide what to discard."
34 core features
triggers
Subscribe at the field level
product.variants.price Subscribe to a field and it won't fire even when title or tag change.Only when the price changesdoes it come through.
query
Define the payload yourself
With a standard Admin GraphQL query, only the exact shape and fields you want — that's what you specify. You aren't bound to a fixed schema, and there's no need to call extra APIs after delivery.
fields_changed
Tells you exactly what changed
Each delivery includes the full path and ID of the changed fields . You no longer need to compute a diff against the previous value or infer the state.
query_filter
Filter on current state
Based on the query result's current state , it decides whether to deliver. Example: product.status:'ACTIVE' to receive only changes to currently published products.
4Legacy Webhooks vs. Next Gen Events
Aspect
Legacy Webhooks
Next Generation Events
Trigger granularity
Per topic all of product/update
Per field e.g. variants.price only
Payload shape
Fixed schema
Your own GraphQL defines it
Extra API calls
Required (you go fetch the fields you want)
Not required
What changed
Receiver computes the diff
fields_changed Stated explicitly
Filtering on current state
Check it yourself after receiving
query_filter Pre-filter with
Where settings live
Admin / API
shopify.app.toml(Git-managed)
Availability
GA
developer preview / unstable
5Configuration example (shopify.app.toml)
An example that subscribes only to price changes, fetches the needed fields with your own GraphQL, and narrows to published products.
The configuration lives as code alongside shopify.app.toml. It can be reviewed in a Pull Request and applied via deploy. The risk of drift from manual admin operations disappears.
Contains the return value of the query you defined. No need to make additional API calls.
fields_changed
Changed fields
Expressed with full paths and IDs....variants[id: ...].price This is the format.
query_variables
Variables used for fetching
Makes explicit which ID was used to fetch. Useful for idempotent processing and log reconciliation.
75 points engineers should keep in mind
1. unstable API = schema changes expected
Because it's a developer preview, the API version is fixed to unstable. Before going to production, you need a mechanism to detect the impact of version updates in CI.
2. Currently two supported topics
As of this article, only Product and Customer are live. Order, Inventory, etc. are not mentioned → replacing existing Webhooks can only proceed gradually.
3. Configuration becomes IaC
Into shopify.app.toml, handle/topic/triggers/uri/query/query_filter everything goes. Review, diff, and rollback are all completed in Git.
4. fields_changed uses full-path notation
Array elements are denoted by variants[id: 'gid://...'].price — a custom syntax.A design that either writes a parser or branches on string matchingshould be decided up front.
5. triggers and query_filter operate at different layers
triggers = Filtering by "what changed" (precondition).query_filter = Filtering by "current state" (postcondition).
Example: combining the two—e.g. "the price changed AND it is currently published"—lets you keep your Webhook design clean and declarative.
8Three use cases you can apply in practice
USE CASE 1
"Noise reduction" and "cost reduction" for core-system integration
Problem
You only want to sync price changes to your ERP/core system, but receiving every product/update and diffing them bloats unnecessary processing and API calls, driving up Cloud Run / Lambda costs.
Solution
In triggers, declare only product.variants.price and compareAtPrice . Include only SKU and price in query. In query_filter, narrow to status:'ACTIVE' .
Result
Fewer deliveries, zero extra API calls, and simpler handler code. Monthly operating costs drop noticeably.
Technical note
Because fields_changed is available, you can pinpoint "which variant's price changed" in one shot. The idempotency key can be built from the ID in query_variables.
USE CASE 2
Capture "only changes in consent state" for CRM / MA integration
Problem
You only want to send updates to a customer's email, tags, and marketing consent to your MA tool, but the Customer update Webhook also fires on other changes such as address, causing false positives on the CRM side.
Solution
Declare field-level triggers on the Customer topic. Fetch only the fields your MA tool needs in query, and limit to the target segment with query_filter.
Result
Only "business-meaningful changes" such as consent withdrawal and tag changes reach the MA tool. Unnecessary automation triggers on the MA side stop firing.
Technical note
Customer is a topic already supported as of this article. If you keep fields_changed as-is in your CRM audit log, it's easy to trace who changed what and when.
USE CASE 3
Integrating "subscription-definition review" into code review for partner development
Problem
In a custom app, engineers set up Webhook subscriptions manually from the admin → settings drift between staging and production, producing bugs that can't be reproduced.
Solution
Consolidate subscription definitions in shopify.app.toml. Review triggers/query/query_filter in a Pull Request, and apply them identically across multiple environments on deploy.
Result
Zero subscription drift between environments, the reasons for configuration changes remain in Git history, and rollback is completed with git revert.
Technical note
Because it is an unstable API, you need a process that runs shopify app deploy --dry-run (or an equivalent check) in CI to detect the impact of schema changes early (stabilization of the API spec has not been announced = not documented).
9A one-line summary you can use in a proposal
"Webhook's 'everything floods in · you need extra APIs · you compute the diffs yourself' — the next-generation subscription model that wipes all that out. Only the fields you want · only the shape you want · only while published you declare it, and can keep it in shopify.app.toml as IaC.
Currently an unstable preview for Product / Customer = adopt early in new development, then replace production in stages."