Shopify Rollouts break a rule that most discount integrations quietly depend on: that a discount's own status tells you whether buyers get it. From Admin GraphQL API 2026-10, a merchant can put a discount inside a Rollout, serve it to a share of traffic, and leave its status, startsAt and endsAt untouched. If your stack syncs, promotes or reports on Shopify discounts, the field you trust can now say the opposite of what the checkout does.
What Shopify shipped on October 1, 2026
Shopify added a read-only rollouts connection to all eight discount types in API version 2026-10, plus root rollouts and rollout(id:) queries, according to the discounts in Rollouts changelog. Merchants use a Rollout to run a sale, a permanent launch or an A/B test, where each treatment goes to a set percentage of shoppers. Discounts are one of four resource families a Rollout can change. The others are catalogs, themes, and checkout and accounts configuration, and the Rollout object reference lists six change types across them.
Reading any of it needs a new read_rollouts scope on top of read_discounts, so existing installs need the merchant to approve again. The release also adds six webhook topics, from rollouts/create to rollouts/resource_change_updated. Two details matter for commerce teams. A discount activated at 100% effective traffic applies on every sales channel, but a partial-traffic activation only applies on the Online Store. And a Rollout has six statuses (draft, scheduled, paused, active, concluded, archived), but only an active one changes what buyers get.
Discount status vs buyer reach: where they now disagree
Discount status and buyer reach disagree in three cases, and each one looks normal from the discount's own fields. A treatment can activate a discount whose dates say SCHEDULED or EXPIRED, so some buyers get a promotion your app thinks is off. Treatments can expire an ACTIVE discount for every buyer, so nobody gets it while your app says it is live. Or a treatment can expire it for part of the traffic only, which is the A/B test case.
The traffic numbers need care too. A Rollout carries trafficAllocation, which is what the merchant configured, and effectiveTrafficAllocation, which is what it gets after Shopify settles overlaps between Rollouts that touch the same discount, theme or catalog. The effective figure can come out lower. Neither number is measured reach, and Shopify's upgrade guide for discount Rollouts says to use them to flag a discount as partial, not to compute exact reach. A Rollout set to 100% that runs a control arm against a treatment arm still gives the discount to only one arm's buyers.
Most integrations still model promotions the old way. A Magento cart price rule has its own active flag and date range, and connectors read those as truth. Plenty of Shopify integrations work the same: poll discounts, read status, mirror it. That breaks the day a merchant tests a 15% offer on half the Online Store traffic.
The silent failure on older API versions
Apps still pinned to 2026-07 or older do not see the conflict at all: Shopify leaves the affected discounts out of their reads. The exclusion applies to discountNode lookups, to the discountNodes, codeDiscountNodes, automaticDiscountNodes and automaticDiscounts connections, to discountNodesCount, and to discount counts on Market. Nothing in the response explains why. The discount comes back when the Rollout stops affecting it.
That is the line in the release we would put in front of every merchant with a custom integration. A sync job that deletes local records when a discount stops appearing will delete live promotions during a test, then recreate them later with new local IDs. Finance then loses the discount a week of orders was booked against. Discount read paths were already shifting, as we noted in automaticDiscounts vs discountNodes. Rollouts adds a harder rule: absence from a read is not deletion.
There is one more trap on the upgrade path. If you add the rollouts selection without the scope, the request returns ACCESS_DENIED, and because the fields on that path are non-null, the error nulls the whole discountNode. Adding the new field to an existing query can take your discount data down with it. Put the Rollout read in its own query, behind a scope check.
What we would change on a Shopify Plus stack this quarter
Upgrade every discount reader to 2026-10, then treat Rollouts as a second source of truth that you reconcile, not a field you bolt on. On the Shopify Plus builds we run, the work splits into four jobs.
- Audit every app and middleware job that reads discounts, including feed tools, loyalty apps and the ERP connector. Note its API version and fix any job that deletes on absence before the upgrade.
- Request
read_rolloutsand plan the reauthorization prompt with the merchant. A scope change on a private app is a five-minute task. On a public app it is a release. - Subscribe to
rollouts/updateand the threeresource_change_*topics, then re-read the discount'srolloutsconnection on each delivery. Payloads carry no treatments or changes, so they are a signal to refetch, not data. Keep a scheduled reconcile as well, because a merchant can pause or conclude a Rollout early and webhooks can be missed. This is the kind of plumbing we build under automation work. - Only promote a discount to buyers, in a channel feed, an email or a storefront banner, when its serving Rollout has an effective allocation of 100 and one treatment activates it at a split of 100. Anything less, or anything your app cannot fully page through, gets treated as restricted.
Reporting needs the same care. A discount that reached 40% of Online Store traffic should not be credited with store-wide lift, so attribute by treatment or label the period as a test.
None of this is an argument against Rollouts. One Rollout can publish a theme, open a catalog and activate a discount together, which is how a real launch works, and on a Shopify Plus vs Magento Hyvä shortlist that coordination is a point for Shopify. Merchants should just switch it on for discounts after every reader is on 2026-10, not before.